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.core.NameValueList;
     30 import gov.nist.javax.sip.SIPConstants;
     31 import gov.nist.javax.sip.Utils;
     32 import gov.nist.javax.sip.address.AddressImpl;
     33 import gov.nist.javax.sip.header.Contact;
     34 import gov.nist.javax.sip.header.RecordRoute;
     35 import gov.nist.javax.sip.header.RecordRouteList;
     36 import gov.nist.javax.sip.header.Route;
     37 import gov.nist.javax.sip.header.RouteList;
     38 import gov.nist.javax.sip.header.TimeStamp;
     39 import gov.nist.javax.sip.header.To;
     40 import gov.nist.javax.sip.header.Via;
     41 import gov.nist.javax.sip.header.ViaList;
     42 import gov.nist.javax.sip.message.SIPMessage;
     43 import gov.nist.javax.sip.message.SIPRequest;
     44 import gov.nist.javax.sip.message.SIPResponse;
     45 
     46 import java.io.IOException;
     47 import java.security.cert.X509Certificate;
     48 import java.text.ParseException;
     49 import java.util.ListIterator;
     50 import java.util.TimerTask;
     51 import java.util.concurrent.ConcurrentHashMap;
     52 
     53 import javax.net.ssl.SSLPeerUnverifiedException;
     54 import javax.sip.Dialog;
     55 import javax.sip.DialogState;
     56 import javax.sip.InvalidArgumentException;
     57 import javax.sip.ObjectInUseException;
     58 import javax.sip.SipException;
     59 import javax.sip.Timeout;
     60 import javax.sip.TimeoutEvent;
     61 import javax.sip.TransactionState;
     62 import javax.sip.address.Hop;
     63 import javax.sip.address.SipURI;
     64 import javax.sip.header.ExpiresHeader;
     65 import javax.sip.header.RouteHeader;
     66 import javax.sip.header.TimeStampHeader;
     67 import javax.sip.message.Request;
     68 
     69 /*
     70  * Jeff Keyser -- initial. Daniel J. Martinez Manzano --Added support for TLS message channel.
     71  * Emil Ivov -- bug fixes. Chris Beardshear -- bug fix. Andreas Bystrom -- bug fixes. Matt Keller
     72  * (Motorolla) -- bug fix.
     73  */
     74 
     75 /**
     76  * Represents a client transaction. Implements the following state machines. (From RFC 3261)
     77  *
     78  * <pre>
     79  *
     80  *
     81  *
     82  *
     83  *
     84  *
     85  *                                                     |INVITE from TU
     86  *                                   Timer A fires     |INVITE sent
     87  *                                   Reset A,          V                      Timer B fires
     88  *                                   INVITE sent +-----------+                or Transport Err.
     89  *                                     +---------|           |---------------+inform TU
     90  *                                     |         |  Calling  |               |
     91  *                                     +--------&gt;|           |--------------&gt;|
     92  *                                               +-----------+ 2xx           |
     93  *                                                  |  |       2xx to TU     |
     94  *                                                  |  |1xx                  |
     95  *                          300-699 +---------------+  |1xx to TU            |
     96  *                         ACK sent |                  |                     |
     97  *                      resp. to TU |  1xx             V                     |
     98  *                                  |  1xx to TU  -----------+               |
     99  *                                  |  +---------|           |               |
    100  *                                  |  |         |Proceeding |--------------&gt;|
    101  *                                  |  +--------&gt;|           | 2xx           |
    102  *                                  |            +-----------+ 2xx to TU     |
    103  *                                  |       300-699    |                     |
    104  *                                  |       ACK sent,  |                     |
    105  *                                  |       resp. to TU|                     |
    106  *                                  |                  |                     |      NOTE:
    107  *                                  |  300-699         V                     |
    108  *                                  |  ACK sent  +-----------+Transport Err. |  transitions
    109  *                                  |  +---------|           |Inform TU      |  labeled with
    110  *                                  |  |         | Completed |--------------&gt;|  the event
    111  *                                  |  +--------&gt;|           |               |  over the action
    112  *                                  |            +-----------+               |  to take
    113  *                                  |              &circ;   |                     |
    114  *                                  |              |   | Timer D fires       |
    115  *                                  +--------------+   | -                   |
    116  *                                                     |                     |
    117  *                                                     V                     |
    118  *                                               +-----------+               |
    119  *                                               |           |               |
    120  *                                               | Terminated|&lt;--------------+
    121  *                                               |           |
    122  *                                               +-----------+
    123  *
    124  *                                       Figure 5: INVITE client transaction
    125  *
    126  *
    127  *                                                         |Request from TU
    128  *                                                         |send request
    129  *                                     Timer E             V
    130  *                                     send request  +-----------+
    131  *                                         +---------|           |-------------------+
    132  *                                         |         |  Trying   |  Timer F          |
    133  *                                         +--------&gt;|           |  or Transport Err.|
    134  *                                                   +-----------+  inform TU        |
    135  *                                      200-699         |  |                         |
    136  *                                      resp. to TU     |  |1xx                      |
    137  *                                      +---------------+  |resp. to TU              |
    138  *                                      |                  |                         |
    139  *                                      |   Timer E        V       Timer F           |
    140  *                                      |   send req +-----------+ or Transport Err. |
    141  *                                      |  +---------|           | inform TU         |
    142  *                                      |  |         |Proceeding |------------------&gt;|
    143  *                                      |  +--------&gt;|           |-----+             |
    144  *                                      |            +-----------+     |1xx          |
    145  *                                      |              |      &circ;        |resp to TU   |
    146  *                                      | 200-699      |      +--------+             |
    147  *                                      | resp. to TU  |                             |
    148  *                                      |              |                             |
    149  *                                      |              V                             |
    150  *                                      |            +-----------+                   |
    151  *                                      |            |           |                   |
    152  *                                      |            | Completed |                   |
    153  *                                      |            |           |                   |
    154  *                                      |            +-----------+                   |
    155  *                                      |              &circ;   |                         |
    156  *                                      |              |   | Timer K                 |
    157  *                                      +--------------+   | -                       |
    158  *                                                         |                         |
    159  *                                                         V                         |
    160  *                                   NOTE:           +-----------+                   |
    161  *                                                   |           |                   |
    162  *                               transitions         | Terminated|&lt;------------------+
    163  *                               labeled with        |           |
    164  *                               the event           +-----------+
    165  *                               over the action
    166  *                               to take
    167  *
    168  *                                       Figure 6: non-INVITE client transaction
    169  *
    170  *
    171  *
    172  *
    173  *
    174  *
    175  * </pre>
    176  *
    177  *
    178  * @author M. Ranganathan
    179  *
    180  * @version 1.2 $Revision: 1.122 $ $Date: 2009/12/17 23:33:52 $
    181  */
    182 public class SIPClientTransaction extends SIPTransaction implements ServerResponseInterface,
    183         javax.sip.ClientTransaction, gov.nist.javax.sip.ClientTransactionExt {
    184 
    185     // a SIP Client transaction may belong simultaneously to multiple
    186     // dialogs in the early state. These dialogs all have
    187     // the same call ID and same From tag but different to tags.
    188 
    189     private ConcurrentHashMap<String,SIPDialog> sipDialogs;
    190 
    191     private SIPRequest lastRequest;
    192 
    193     private int viaPort;
    194 
    195     private String viaHost;
    196 
    197     // Real ResponseInterface to pass messages to
    198     private transient ServerResponseInterface respondTo;
    199 
    200     private SIPDialog defaultDialog;
    201 
    202     private Hop nextHop;
    203 
    204     private boolean notifyOnRetransmit;
    205 
    206     private boolean timeoutIfStillInCallingState;
    207 
    208     private int callingStateTimeoutCount;
    209 
    210     public class TransactionTimer extends SIPStackTimerTask {
    211 
    212         public TransactionTimer() {
    213 
    214         }
    215 
    216         protected void runTask() {
    217             SIPClientTransaction clientTransaction;
    218             SIPTransactionStack sipStack;
    219             clientTransaction = SIPClientTransaction.this;
    220             sipStack = clientTransaction.sipStack;
    221 
    222             // If the transaction has terminated,
    223             if (clientTransaction.isTerminated()) {
    224 
    225                 if (sipStack.isLoggingEnabled()) {
    226                     sipStack.getStackLogger().logDebug(
    227                             "removing  = " + clientTransaction + " isReliable "
    228                                     + clientTransaction.isReliable());
    229                 }
    230 
    231                 sipStack.removeTransaction(clientTransaction);
    232 
    233                 try {
    234                     this.cancel();
    235 
    236                 } catch (IllegalStateException ex) {
    237                     if (!sipStack.isAlive())
    238                         return;
    239                 }
    240 
    241                 // Client transaction terminated. Kill connection if
    242                 // this is a TCP after the linger timer has expired.
    243                 // The linger timer is needed to allow any pending requests to
    244                 // return responses.
    245                 if ((!sipStack.cacheClientConnections) && clientTransaction.isReliable()) {
    246 
    247                     int newUseCount = --clientTransaction.getMessageChannel().useCount;
    248                     if (newUseCount <= 0) {
    249                         // Let the connection linger for a while and then close
    250                         // it.
    251                         TimerTask myTimer = new LingerTimer();
    252                         sipStack.getTimer().schedule(myTimer,
    253                                 SIPTransactionStack.CONNECTION_LINGER_TIME * 1000);
    254                     }
    255 
    256                 } else {
    257                     // Cache the client connections so dont close the
    258                     // connection. This keeps the connection open permanently
    259                     // until the client disconnects.
    260                     if (sipStack.isLoggingEnabled() && clientTransaction.isReliable()) {
    261                        	int useCount = clientTransaction.getMessageChannel().useCount;
    262                        	if (sipStack.isLoggingEnabled())
    263                        		sipStack.getStackLogger().logDebug("Client Use Count = " + useCount);
    264                     }
    265                 }
    266 
    267             } else {
    268                 // If this transaction has not
    269                 // terminated,
    270                 // Fire the transaction timer.
    271                 clientTransaction.fireTimer();
    272 
    273             }
    274 
    275         }
    276 
    277     }
    278 
    279     /**
    280      * Creates a new client transaction.
    281      *
    282      * @param newSIPStack Transaction stack this transaction belongs to.
    283      * @param newChannelToUse Channel to encapsulate.
    284      * @return the created client transaction.
    285      */
    286     protected SIPClientTransaction(SIPTransactionStack newSIPStack, MessageChannel newChannelToUse) {
    287         super(newSIPStack, newChannelToUse);
    288         // Create a random branch parameter for this transaction
    289         // setBranch( SIPConstants.BRANCH_MAGIC_COOKIE +
    290         // Integer.toHexString( hashCode( ) ) );
    291         setBranch(Utils.getInstance().generateBranchId());
    292         this.messageProcessor = newChannelToUse.messageProcessor;
    293         this.setEncapsulatedChannel(newChannelToUse);
    294         this.notifyOnRetransmit = false;
    295         this.timeoutIfStillInCallingState = false;
    296 
    297         // This semaphore guards the listener from being
    298         // re-entered for this transaction. That is
    299         // for a give tx, the listener is called at most
    300         // once with an outstanding request.
    301 
    302         if (sipStack.isLoggingEnabled()) {
    303             sipStack.getStackLogger().logDebug("Creating clientTransaction " + this);
    304             sipStack.getStackLogger().logStackTrace();
    305         }
    306         // this.startTransactionTimer();
    307         this.sipDialogs = new ConcurrentHashMap();
    308     }
    309 
    310     /**
    311      * Sets the real ResponseInterface this transaction encapsulates.
    312      *
    313      * @param newRespondTo ResponseInterface to send messages to.
    314      */
    315     public void setResponseInterface(ServerResponseInterface newRespondTo) {
    316         if (sipStack.isLoggingEnabled()) {
    317             sipStack.getStackLogger().logDebug(
    318                     "Setting response interface for " + this + " to " + newRespondTo);
    319             if (newRespondTo == null) {
    320                 sipStack.getStackLogger().logStackTrace();
    321                 sipStack.getStackLogger().logDebug("WARNING -- setting to null!");
    322             }
    323         }
    324 
    325         respondTo = newRespondTo;
    326 
    327     }
    328 
    329     /**
    330      * Returns this transaction.
    331      */
    332     public MessageChannel getRequestChannel() {
    333 
    334         return this;
    335 
    336     }
    337 
    338     /**
    339      * Deterines if the message is a part of this transaction.
    340      *
    341      * @param messageToTest Message to check if it is part of this transaction.
    342      *
    343      * @return true if the message is part of this transaction, false if not.
    344      */
    345     public boolean isMessagePartOfTransaction(SIPMessage messageToTest) {
    346 
    347         // List of Via headers in the message to test
    348         ViaList viaHeaders = messageToTest.getViaHeaders();
    349         // Flags whether the select message is part of this transaction
    350         boolean transactionMatches;
    351         String messageBranch = ((Via) viaHeaders.getFirst()).getBranch();
    352         boolean rfc3261Compliant = getBranch() != null
    353                 && messageBranch != null
    354                 && getBranch().toLowerCase().startsWith(
    355                         SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)
    356                 && messageBranch.toLowerCase().startsWith(
    357                         SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE);
    358 
    359         transactionMatches = false;
    360         if (TransactionState.COMPLETED == this.getState()) {
    361             if (rfc3261Compliant) {
    362                 transactionMatches = getBranch().equalsIgnoreCase(
    363                         ((Via) viaHeaders.getFirst()).getBranch())
    364                         && getMethod().equals(messageToTest.getCSeq().getMethod());
    365             } else {
    366                 transactionMatches = getBranch().equals(messageToTest.getTransactionId());
    367             }
    368         } else if (!isTerminated()) {
    369             if (rfc3261Compliant) {
    370                 if (viaHeaders != null) {
    371                     // If the branch parameter is the
    372                     // same as this transaction and the method is the same,
    373                     if (getBranch().equalsIgnoreCase(((Via) viaHeaders.getFirst()).getBranch())) {
    374                         transactionMatches = getOriginalRequest().getCSeq().getMethod().equals(
    375                                 messageToTest.getCSeq().getMethod());
    376 
    377                     }
    378                 }
    379             } else {
    380                 // not RFC 3261 compliant.
    381                 if (getBranch() != null) {
    382                     transactionMatches = getBranch().equalsIgnoreCase(
    383                             messageToTest.getTransactionId());
    384                 } else {
    385                     transactionMatches = getOriginalRequest().getTransactionId()
    386                             .equalsIgnoreCase(messageToTest.getTransactionId());
    387                 }
    388 
    389             }
    390 
    391         }
    392         return transactionMatches;
    393 
    394     }
    395 
    396     /**
    397      * Send a request message through this transaction and onto the client.
    398      *
    399      * @param messageToSend Request to process and send.
    400      */
    401     public void sendMessage(SIPMessage messageToSend) throws IOException {
    402 
    403         try {
    404             // Message typecast as a request
    405             SIPRequest transactionRequest;
    406 
    407             transactionRequest = (SIPRequest) messageToSend;
    408 
    409             // Set the branch id for the top via header.
    410             Via topVia = (Via) transactionRequest.getViaHeaders().getFirst();
    411             // Tack on a branch identifier to match responses.
    412             try {
    413                 topVia.setBranch(getBranch());
    414             } catch (java.text.ParseException ex) {
    415             }
    416 
    417             if (sipStack.isLoggingEnabled()) {
    418                 sipStack.getStackLogger().logDebug("Sending Message " + messageToSend);
    419                 sipStack.getStackLogger().logDebug("TransactionState " + this.getState());
    420             }
    421             // If this is the first request for this transaction,
    422             if (TransactionState.PROCEEDING == getState()
    423                     || TransactionState.CALLING == getState()) {
    424 
    425                 // If this is a TU-generated ACK request,
    426                 if (transactionRequest.getMethod().equals(Request.ACK)) {
    427 
    428                     // Send directly to the underlying
    429                     // transport and close this transaction
    430                     if (isReliable()) {
    431                         this.setState(TransactionState.TERMINATED);
    432                     } else {
    433                         this.setState(TransactionState.COMPLETED);
    434                     }
    435                     // BUGBUG -- This suppresses sending the ACK uncomment this
    436                     // to
    437                     // test 4xx retransmission
    438                     // if (transactionRequest.getMethod() != Request.ACK)
    439                     super.sendMessage(transactionRequest);
    440                     return;
    441 
    442                 }
    443 
    444             }
    445             try {
    446 
    447                 // Send the message to the server
    448                 lastRequest = transactionRequest;
    449                 if (getState() == null) {
    450                     // Save this request as the one this transaction
    451                     // is handling
    452                     setOriginalRequest(transactionRequest);
    453                     // Change to trying/calling state
    454                     // Set state first to avoid race condition..
    455 
    456                     if (transactionRequest.getMethod().equals(Request.INVITE)) {
    457                         this.setState(TransactionState.CALLING);
    458                     } else if (transactionRequest.getMethod().equals(Request.ACK)) {
    459                         // Acks are never retransmitted.
    460                         this.setState(TransactionState.TERMINATED);
    461                     } else {
    462                         this.setState(TransactionState.TRYING);
    463                     }
    464                     if (!isReliable()) {
    465                         enableRetransmissionTimer();
    466                     }
    467                     if (isInviteTransaction()) {
    468                         enableTimeoutTimer(TIMER_B);
    469                     } else {
    470                         enableTimeoutTimer(TIMER_F);
    471                     }
    472                 }
    473                 // BUGBUG This supresses sending ACKS -- uncomment to test
    474                 // 4xx retransmission.
    475                 // if (transactionRequest.getMethod() != Request.ACK)
    476                 super.sendMessage(transactionRequest);
    477 
    478             } catch (IOException e) {
    479 
    480                 this.setState(TransactionState.TERMINATED);
    481                 throw e;
    482 
    483             }
    484         } finally {
    485             this.isMapped = true;
    486             this.startTransactionTimer();
    487 
    488         }
    489 
    490     }
    491 
    492     /**
    493      * Process a new response message through this transaction. If necessary, this message will
    494      * also be passed onto the TU.
    495      *
    496      * @param transactionResponse Response to process.
    497      * @param sourceChannel Channel that received this message.
    498      */
    499     public synchronized void processResponse(SIPResponse transactionResponse,
    500             MessageChannel sourceChannel, SIPDialog dialog) {
    501 
    502         // If the state has not yet been assigned then this is a
    503         // spurious response.
    504 
    505         if (getState() == null)
    506             return;
    507 
    508         // Ignore 1xx
    509         if ((TransactionState.COMPLETED == this.getState() || TransactionState.TERMINATED == this
    510                 .getState())
    511                 && transactionResponse.getStatusCode() / 100 == 1) {
    512             return;
    513         }
    514 
    515         if (sipStack.isLoggingEnabled()) {
    516             sipStack.getStackLogger().logDebug(
    517                     "processing " + transactionResponse.getFirstLine() + "current state = "
    518                             + getState());
    519             sipStack.getStackLogger().logDebug("dialog = " + dialog);
    520         }
    521 
    522         this.lastResponse = transactionResponse;
    523 
    524         /*
    525          * JvB: this is now duplicate with code in the other processResponse
    526          *
    527          * if (dialog != null && transactionResponse.getStatusCode() != 100 &&
    528          * (transactionResponse.getTo().getTag() != null || sipStack .isRfc2543Supported())) { //
    529          * add the route before you process the response. dialog.setLastResponse(this,
    530          * transactionResponse); this.setDialog(dialog, transactionResponse.getDialogId(false)); }
    531          */
    532 
    533         try {
    534             if (isInviteTransaction())
    535                 inviteClientTransaction(transactionResponse, sourceChannel, dialog);
    536             else
    537                 nonInviteClientTransaction(transactionResponse, sourceChannel, dialog);
    538         } catch (IOException ex) {
    539             if (sipStack.isLoggingEnabled())
    540                 sipStack.getStackLogger().logException(ex);
    541             this.setState(TransactionState.TERMINATED);
    542             raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
    543         }
    544     }
    545 
    546     /**
    547      * Implements the state machine for invite client transactions.
    548      *
    549      * <pre>
    550      *
    551      *
    552      *
    553      *
    554      *
    555      *                                                         |Request from TU
    556      *                                                         |send request
    557      *                                     Timer E             V
    558      *                                     send request  +-----------+
    559      *                                         +---------|           |-------------------+
    560      *                                         |         |  Trying   |  Timer F          |
    561      *                                         +--------&gt;|           |  or Transport Err.|
    562      *                                                   +-----------+  inform TU        |
    563      *                                      200-699         |  |                         |
    564      *                                      resp. to TU     |  |1xx                      |
    565      *                                      +---------------+  |resp. to TU              |
    566      *                                      |                  |                         |
    567      *                                      |   Timer E        V       Timer F           |
    568      *                                      |   send req +-----------+ or Transport Err. |
    569      *                                      |  +---------|           | inform TU         |
    570      *                                      |  |         |Proceeding |------------------&gt;|
    571      *                                      |  +--------&gt;|           |-----+             |
    572      *                                      |            +-----------+     |1xx          |
    573      *                                      |              |      &circ;        |resp to TU   |
    574      *                                      | 200-699      |      +--------+             |
    575      *                                      | resp. to TU  |                             |
    576      *                                      |              |                             |
    577      *                                      |              V                             |
    578      *                                      |            +-----------+                   |
    579      *                                      |            |           |                   |
    580      *                                      |            | Completed |                   |
    581      *                                      |            |           |                   |
    582      *                                      |            +-----------+                   |
    583      *                                      |              &circ;   |                         |
    584      *                                      |              |   | Timer K                 |
    585      *                                      +--------------+   | -                       |
    586      *                                                         |                         |
    587      *                                                         V                         |
    588      *                                   NOTE:           +-----------+                   |
    589      *                                                   |           |                   |
    590      *                               transitions         | Terminated|&lt;------------------+
    591      *                               labeled with        |           |
    592      *                               the event           +-----------+
    593      *                               over the action
    594      *                               to take
    595      *
    596      *                                       Figure 6: non-INVITE client transaction
    597      *
    598      *
    599      *
    600      *
    601      * </pre>
    602      *
    603      * @param transactionResponse -- transaction response received.
    604      * @param sourceChannel - source channel on which the response was received.
    605      */
    606     private void nonInviteClientTransaction(SIPResponse transactionResponse,
    607             MessageChannel sourceChannel, SIPDialog sipDialog) throws IOException {
    608         int statusCode = transactionResponse.getStatusCode();
    609         if (TransactionState.TRYING == this.getState()) {
    610             if (statusCode / 100 == 1) {
    611                 this.setState(TransactionState.PROCEEDING);
    612                 enableRetransmissionTimer(MAXIMUM_RETRANSMISSION_TICK_COUNT);
    613                 enableTimeoutTimer(TIMER_F);
    614                 // According to RFC, the TU has to be informed on
    615                 // this transition.
    616                 if (respondTo != null) {
    617                     respondTo.processResponse(transactionResponse, this, sipDialog);
    618                 } else {
    619                     this.semRelease();
    620                 }
    621             } else if (200 <= statusCode && statusCode <= 699) {
    622                 // Send the response up to the TU.
    623                 if (respondTo != null) {
    624                     respondTo.processResponse(transactionResponse, this, sipDialog);
    625                 } else {
    626                     this.semRelease();
    627                 }
    628                 if (!isReliable()) {
    629                     this.setState(TransactionState.COMPLETED);
    630                     enableTimeoutTimer(TIMER_K);
    631                 } else {
    632                     this.setState(TransactionState.TERMINATED);
    633                 }
    634             }
    635         } else if (TransactionState.PROCEEDING == this.getState()) {
    636             if (statusCode / 100 == 1) {
    637                 if (respondTo != null) {
    638                     respondTo.processResponse(transactionResponse, this, sipDialog);
    639                 } else {
    640                     this.semRelease();
    641                 }
    642             } else if (200 <= statusCode && statusCode <= 699) {
    643                 if (respondTo != null) {
    644                     respondTo.processResponse(transactionResponse, this, sipDialog);
    645                 } else {
    646                     this.semRelease();
    647                 }
    648                 disableRetransmissionTimer();
    649                 disableTimeoutTimer();
    650                 if (!isReliable()) {
    651                     this.setState(TransactionState.COMPLETED);
    652                     enableTimeoutTimer(TIMER_K);
    653                 } else {
    654                     this.setState(TransactionState.TERMINATED);
    655                 }
    656             }
    657         } else {
    658             if (sipStack.isLoggingEnabled()) {
    659                 sipStack.getStackLogger().logDebug(
    660                         " Not sending response to TU! " + getState());
    661             }
    662             this.semRelease();
    663         }
    664     }
    665 
    666     /**
    667      * Implements the state machine for invite client transactions.
    668      *
    669      * <pre>
    670      *
    671      *
    672      *
    673      *
    674      *
    675      *                                                     |INVITE from TU
    676      *                                   Timer A fires     |INVITE sent
    677      *                                   Reset A,          V                      Timer B fires
    678      *                                   INVITE sent +-----------+                or Transport Err.
    679      *                                     +---------|           |---------------+inform TU
    680      *                                     |         |  Calling  |               |
    681      *                                     +--------&gt;|           |--------------&gt;|
    682      *                                               +-----------+ 2xx           |
    683      *                                                  |  |       2xx to TU     |
    684      *                                                  |  |1xx                  |
    685      *                          300-699 +---------------+  |1xx to TU            |
    686      *                         ACK sent |                  |                     |
    687      *                      resp. to TU |  1xx             V                     |
    688      *                                  |  1xx to TU  -----------+               |
    689      *                                  |  +---------|           |               |
    690      *                                  |  |         |Proceeding |--------------&gt;|
    691      *                                  |  +--------&gt;|           | 2xx           |
    692      *                                  |            +-----------+ 2xx to TU     |
    693      *                                  |       300-699    |                     |
    694      *                                  |       ACK sent,  |                     |
    695      *                                  |       resp. to TU|                     |
    696      *                                  |                  |                     |      NOTE:
    697      *                                  |  300-699         V                     |
    698      *                                  |  ACK sent  +-----------+Transport Err. |  transitions
    699      *                                  |  +---------|           |Inform TU      |  labeled with
    700      *                                  |  |         | Completed |--------------&gt;|  the event
    701      *                                  |  +--------&gt;|           |               |  over the action
    702      *                                  |            +-----------+               |  to take
    703      *                                  |              &circ;   |                     |
    704      *                                  |              |   | Timer D fires       |
    705      *                                  +--------------+   | -                   |
    706      *                                                     |                     |
    707      *                                                     V                     |
    708      *                                               +-----------+               |
    709      *                                               |           |               |
    710      *                                               | Terminated|&lt;--------------+
    711      *                                               |           |
    712      *                                               +-----------+
    713      *
    714      *
    715      *
    716      *
    717      * </pre>
    718      *
    719      * @param transactionResponse -- transaction response received.
    720      * @param sourceChannel - source channel on which the response was received.
    721      */
    722 
    723     private void inviteClientTransaction(SIPResponse transactionResponse,
    724             MessageChannel sourceChannel, SIPDialog dialog) throws IOException {
    725         int statusCode = transactionResponse.getStatusCode();
    726 
    727         if (TransactionState.TERMINATED == this.getState()) {
    728             boolean ackAlreadySent = false;
    729             if (dialog != null && dialog.isAckSeen() && dialog.getLastAckSent() != null) {
    730                 if (dialog.getLastAckSent().getCSeq().getSeqNumber() == transactionResponse.getCSeq()
    731                         .getSeqNumber()
    732                         && transactionResponse.getFromTag().equals(
    733                                 dialog.getLastAckSent().getFromTag())) {
    734                     // the last ack sent corresponded to this response
    735                     ackAlreadySent = true;
    736                 }
    737             }
    738             // retransmit the ACK for this response.
    739             if (dialog!= null && ackAlreadySent
    740                     && transactionResponse.getCSeq().getMethod().equals(dialog.getMethod())) {
    741                 try {
    742                     // Found the dialog - resend the ACK and
    743                     // dont pass up the null transaction
    744                     if (sipStack.isLoggingEnabled())
    745                         sipStack.getStackLogger().logDebug("resending ACK");
    746 
    747                     dialog.resendAck();
    748                 } catch (SipException ex) {
    749                     // What to do here ?? kill the dialog?
    750                 }
    751             }
    752 
    753             this.semRelease();
    754             return;
    755         } else if (TransactionState.CALLING == this.getState()) {
    756             if (statusCode / 100 == 2) {
    757 
    758                 // JvB: do this ~before~ calling the application, to avoid
    759                 // retransmissions
    760                 // of the INVITE after app sends ACK
    761                 disableRetransmissionTimer();
    762                 disableTimeoutTimer();
    763                 this.setState(TransactionState.TERMINATED);
    764 
    765                 // 200 responses are always seen by TU.
    766                 if (respondTo != null)
    767                     respondTo.processResponse(transactionResponse, this, dialog);
    768                 else {
    769                     this.semRelease();
    770                 }
    771 
    772             } else if (statusCode / 100 == 1) {
    773                 disableRetransmissionTimer();
    774                 disableTimeoutTimer();
    775                 this.setState(TransactionState.PROCEEDING);
    776 
    777                 if (respondTo != null)
    778                     respondTo.processResponse(transactionResponse, this, dialog);
    779                 else {
    780                     this.semRelease();
    781                 }
    782 
    783             } else if (300 <= statusCode && statusCode <= 699) {
    784                 // Send back an ACK request
    785 
    786                 try {
    787                     sendMessage((SIPRequest) createErrorAck());
    788 
    789                 } catch (Exception ex) {
    790                     sipStack.getStackLogger().logError(
    791                             "Unexpected Exception sending ACK -- sending error AcK ", ex);
    792 
    793                 }
    794 
    795                 /*
    796                  * When in either the "Calling" or "Proceeding" states, reception of response with
    797                  * status code from 300-699 MUST cause the client transaction to transition to
    798                  * "Completed". The client transaction MUST pass the received response up to the
    799                  * TU, and the client transaction MUST generate an ACK request.
    800                  */
    801 
    802                 if (respondTo != null) {
    803                     respondTo.processResponse(transactionResponse, this, dialog);
    804                 } else {
    805                     this.semRelease();
    806                 }
    807 
    808                 if (this.getDialog() != null &&  ((SIPDialog)this.getDialog()).isBackToBackUserAgent()) {
    809                     ((SIPDialog) this.getDialog()).releaseAckSem();
    810                 }
    811 
    812                 if (!isReliable()) {
    813                     this.setState(TransactionState.COMPLETED);
    814                     enableTimeoutTimer(TIMER_D);
    815                 } else {
    816                     // Proceed immediately to the TERMINATED state.
    817                     this.setState(TransactionState.TERMINATED);
    818                 }
    819             }
    820         } else if (TransactionState.PROCEEDING == this.getState()) {
    821             if (statusCode / 100 == 1) {
    822                 if (respondTo != null) {
    823                     respondTo.processResponse(transactionResponse, this, dialog);
    824                 } else {
    825                     this.semRelease();
    826                 }
    827             } else if (statusCode / 100 == 2) {
    828                 this.setState(TransactionState.TERMINATED);
    829                 if (respondTo != null) {
    830                     respondTo.processResponse(transactionResponse, this, dialog);
    831                 } else {
    832                     this.semRelease();
    833                 }
    834 
    835             } else if (300 <= statusCode && statusCode <= 699) {
    836                 // Send back an ACK request
    837                 try {
    838                     sendMessage((SIPRequest) createErrorAck());
    839                 } catch (Exception ex) {
    840                     InternalErrorHandler.handleException(ex);
    841                 }
    842 
    843                 if (this.getDialog() != null) {
    844                     ((SIPDialog) this.getDialog()).releaseAckSem();
    845                 }
    846                 // JvB: update state before passing to app
    847                 if (!isReliable()) {
    848                     this.setState(TransactionState.COMPLETED);
    849                     this.enableTimeoutTimer(TIMER_D);
    850                 } else {
    851                     this.setState(TransactionState.TERMINATED);
    852                 }
    853 
    854                 // Pass up to the TU for processing.
    855                 if (respondTo != null)
    856                     respondTo.processResponse(transactionResponse, this, dialog);
    857                 else {
    858                     this.semRelease();
    859                 }
    860 
    861                 // JvB: duplicate with line 874
    862                 // if (!isReliable()) {
    863                 // enableTimeoutTimer(TIMER_D);
    864                 // }
    865             }
    866         } else if (TransactionState.COMPLETED == this.getState()) {
    867             if (300 <= statusCode && statusCode <= 699) {
    868                 // Send back an ACK request
    869                 try {
    870                     sendMessage((SIPRequest) createErrorAck());
    871                 } catch (Exception ex) {
    872                     InternalErrorHandler.handleException(ex);
    873                 } finally {
    874                     this.semRelease();
    875                 }
    876             }
    877 
    878         }
    879 
    880     }
    881 
    882     /*
    883      * (non-Javadoc)
    884      *
    885      * @see javax.sip.ClientTransaction#sendRequest()
    886      */
    887     public void sendRequest() throws SipException {
    888         SIPRequest sipRequest = this.getOriginalRequest();
    889 
    890         if (this.getState() != null)
    891             throw new SipException("Request already sent");
    892 
    893         if (sipStack.isLoggingEnabled()) {
    894             sipStack.getStackLogger().logDebug("sendRequest() " + sipRequest);
    895         }
    896 
    897         try {
    898             sipRequest.checkHeaders();
    899         } catch (ParseException ex) {
    900         	if (sipStack.isLoggingEnabled())
    901         		sipStack.getStackLogger().logError("missing required header");
    902             throw new SipException(ex.getMessage());
    903         }
    904 
    905         if (getMethod().equals(Request.SUBSCRIBE)
    906                 && sipRequest.getHeader(ExpiresHeader.NAME) == null) {
    907             /*
    908              * If no "Expires" header is present in a SUBSCRIBE request, the implied default is
    909              * defined by the event package being used.
    910              *
    911              */
    912         	if (sipStack.isLoggingEnabled())
    913         		sipStack.getStackLogger().logWarning(
    914                     "Expires header missing in outgoing subscribe --"
    915                             + " Notifier will assume implied value on event package");
    916         }
    917         try {
    918             /*
    919              * This check is removed because it causes problems for load balancers ( See issue
    920              * 136) reported by Raghav Ramesh ( BT )
    921              *
    922              */
    923             if (this.getOriginalRequest().getMethod().equals(Request.CANCEL)
    924                     && sipStack.isCancelClientTransactionChecked()) {
    925                 SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction(
    926                         this.getOriginalRequest(), false);
    927                 if (ct == null) {
    928                     /*
    929                      * If the original request has generated a final response, the CANCEL SHOULD
    930                      * NOT be sent, as it is an effective no-op, since CANCEL has no effect on
    931                      * requests that have already generated a final response.
    932                      */
    933                     throw new SipException("Could not find original tx to cancel. RFC 3261 9.1");
    934                 } else if (ct.getState() == null) {
    935                     throw new SipException(
    936                             "State is null no provisional response yet -- cannot cancel RFC 3261 9.1");
    937                 } else if (!ct.getMethod().equals(Request.INVITE)) {
    938                     throw new SipException("Cannot cancel non-invite requests RFC 3261 9.1");
    939                 }
    940             } else
    941 
    942             if (this.getOriginalRequest().getMethod().equals(Request.BYE)
    943                     || this.getOriginalRequest().getMethod().equals(Request.NOTIFY)) {
    944                 SIPDialog dialog = sipStack.getDialog(this.getOriginalRequest()
    945                         .getDialogId(false));
    946                 // I want to behave like a user agent so send the BYE using the
    947                 // Dialog
    948                 if (this.getSipProvider().isAutomaticDialogSupportEnabled() && dialog != null) {
    949                     throw new SipException(
    950                             "Dialog is present and AutomaticDialogSupport is enabled for "
    951                                     + " the provider -- Send the Request using the Dialog.sendRequest(transaction)");
    952                 }
    953             }
    954             // Only map this after the fist request is sent out.
    955             if (this.getMethod().equals(Request.INVITE)) {
    956                 SIPDialog dialog = this.getDefaultDialog();
    957 
    958                 if (dialog != null && dialog.isBackToBackUserAgent()) {
    959                     // Block sending re-INVITE till we see the ACK.
    960                     if ( ! dialog.takeAckSem() ) {
    961                         throw new SipException ("Failed to take ACK semaphore");
    962                     }
    963 
    964                 }
    965             }
    966             this.isMapped = true;
    967             this.sendMessage(sipRequest);
    968 
    969         } catch (IOException ex) {
    970             this.setState(TransactionState.TERMINATED);
    971             throw new SipException("IO Error sending request", ex);
    972 
    973         }
    974 
    975     }
    976 
    977     /**
    978      * Called by the transaction stack when a retransmission timer fires.
    979      */
    980     protected void fireRetransmissionTimer() {
    981 
    982         try {
    983 
    984             // Resend the last request sent
    985             if (this.getState() == null || !this.isMapped)
    986                 return;
    987 
    988             boolean inv = isInviteTransaction();
    989             TransactionState s = this.getState();
    990 
    991             // JvB: INVITE CTs only retransmit in CALLING, non-INVITE in both TRYING and
    992             // PROCEEDING
    993             // Bug-fix for non-INVITE transactions not retransmitted when 1xx response received
    994             if ((inv && TransactionState.CALLING == s)
    995                     || (!inv && (TransactionState.TRYING == s || TransactionState.PROCEEDING == s))) {
    996                 // If the retransmission filter is disabled then
    997                 // retransmission of the INVITE is the application
    998                 // responsibility.
    999 
   1000                 if (lastRequest != null) {
   1001                     if (sipStack.generateTimeStampHeader
   1002                             && lastRequest.getHeader(TimeStampHeader.NAME) != null) {
   1003                         long milisec = System.currentTimeMillis();
   1004                         TimeStamp timeStamp = new TimeStamp();
   1005                         try {
   1006                             timeStamp.setTimeStamp(milisec);
   1007                         } catch (InvalidArgumentException ex) {
   1008                             InternalErrorHandler.handleException(ex);
   1009                         }
   1010                         lastRequest.setHeader(timeStamp);
   1011                     }
   1012                     super.sendMessage(lastRequest);
   1013                     if (this.notifyOnRetransmit) {
   1014                         TimeoutEvent txTimeout = new TimeoutEvent(this.getSipProvider(), this,
   1015                                 Timeout.RETRANSMIT);
   1016                         this.getSipProvider().handleEvent(txTimeout, this);
   1017                     }
   1018                     if (this.timeoutIfStillInCallingState
   1019                             && this.getState() == TransactionState.CALLING) {
   1020                         this.callingStateTimeoutCount--;
   1021                         if (callingStateTimeoutCount == 0) {
   1022                             TimeoutEvent timeoutEvent = new TimeoutEvent(this.getSipProvider(),
   1023                                     this, Timeout.RETRANSMIT);
   1024                             this.getSipProvider().handleEvent(timeoutEvent, this);
   1025                             this.timeoutIfStillInCallingState = false;
   1026                         }
   1027 
   1028                     }
   1029                 }
   1030 
   1031             }
   1032         } catch (IOException e) {
   1033             this.raiseIOExceptionEvent();
   1034             raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
   1035         }
   1036 
   1037     }
   1038 
   1039     /**
   1040      * Called by the transaction stack when a timeout timer fires.
   1041      */
   1042     protected void fireTimeoutTimer() {
   1043 
   1044         if (sipStack.isLoggingEnabled())
   1045             sipStack.getStackLogger().logDebug("fireTimeoutTimer " + this);
   1046 
   1047         SIPDialog dialog = (SIPDialog) this.getDialog();
   1048         if (TransactionState.CALLING == this.getState()
   1049                 || TransactionState.TRYING == this.getState()
   1050                 || TransactionState.PROCEEDING == this.getState()) {
   1051             // Timeout occured. If this is asociated with a transaction
   1052             // creation then kill the dialog.
   1053             if (dialog != null
   1054                     && (dialog.getState() == null || dialog.getState() == DialogState.EARLY)) {
   1055                 if (((SIPTransactionStack) getSIPStack()).isDialogCreated(this
   1056                         .getOriginalRequest().getMethod())) {
   1057                     // If this is a re-invite we do not delete the dialog even
   1058                     // if the
   1059                     // reinvite times out. Else
   1060                     // terminate the enclosing dialog.
   1061                     dialog.delete();
   1062                 }
   1063             } else if (dialog != null) {
   1064                 // Guard against the case of BYE time out.
   1065 
   1066                 if (getOriginalRequest().getMethod().equalsIgnoreCase(Request.BYE)
   1067                         && dialog.isTerminatedOnBye()) {
   1068                     // Terminate the associated dialog on BYE Timeout.
   1069                     dialog.delete();
   1070                 }
   1071             }
   1072         }
   1073         if (TransactionState.COMPLETED != this.getState()) {
   1074             raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
   1075             // Got a timeout error on a cancel.
   1076             if (this.getOriginalRequest().getMethod().equalsIgnoreCase(Request.CANCEL)) {
   1077                 SIPClientTransaction inviteTx = (SIPClientTransaction) this.getOriginalRequest()
   1078                         .getInviteTransaction();
   1079                 if (inviteTx != null
   1080                         && ((inviteTx.getState() == TransactionState.CALLING || inviteTx
   1081                                 .getState() == TransactionState.PROCEEDING))
   1082                         && inviteTx.getDialog() != null) {
   1083                     /*
   1084                      * A proxy server should have started TIMER C and take care of the Termination
   1085                      * using transaction.terminate() by itself (i.e. this is not the job of the
   1086                      * stack at this point but we do it to be nice.
   1087                      */
   1088                     inviteTx.setState(TransactionState.TERMINATED);
   1089 
   1090                 }
   1091             }
   1092 
   1093         } else {
   1094             this.setState(TransactionState.TERMINATED);
   1095         }
   1096 
   1097     }
   1098 
   1099     /*
   1100      * (non-Javadoc)
   1101      *
   1102      * @see javax.sip.ClientTransaction#createCancel()
   1103      */
   1104     public Request createCancel() throws SipException {
   1105         SIPRequest originalRequest = this.getOriginalRequest();
   1106         if (originalRequest == null)
   1107             throw new SipException("Bad state " + getState());
   1108         if (!originalRequest.getMethod().equals(Request.INVITE))
   1109             throw new SipException("Only INIVTE may be cancelled");
   1110 
   1111         if (originalRequest.getMethod().equalsIgnoreCase(Request.ACK))
   1112             throw new SipException("Cannot Cancel ACK!");
   1113         else {
   1114             SIPRequest cancelRequest = originalRequest.createCancelRequest();
   1115             cancelRequest.setInviteTransaction(this);
   1116             return cancelRequest;
   1117         }
   1118     }
   1119 
   1120     /*
   1121      * (non-Javadoc)
   1122      *
   1123      * @see javax.sip.ClientTransaction#createAck()
   1124      */
   1125     public Request createAck() throws SipException {
   1126         SIPRequest originalRequest = this.getOriginalRequest();
   1127         if (originalRequest == null)
   1128             throw new SipException("bad state " + getState());
   1129         if (getMethod().equalsIgnoreCase(Request.ACK)) {
   1130             throw new SipException("Cannot ACK an ACK!");
   1131         } else if (lastResponse == null) {
   1132             throw new SipException("bad Transaction state");
   1133         } else if (lastResponse.getStatusCode() < 200) {
   1134             if (sipStack.isLoggingEnabled()) {
   1135                 sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
   1136             }
   1137             throw new SipException("Cannot ACK a provisional response!");
   1138         }
   1139         SIPRequest ackRequest = originalRequest.createAckRequest((To) lastResponse.getTo());
   1140         // Pull the record route headers from the last reesponse.
   1141         RecordRouteList recordRouteList = lastResponse.getRecordRouteHeaders();
   1142         if (recordRouteList == null) {
   1143             // If the record route list is null then we can
   1144             // construct the ACK from the specified contact header.
   1145             // Note the 3xx check here because 3xx is a redirect.
   1146             // The contact header for the 3xx is the redirected
   1147             // location so we cannot use that to construct the
   1148             // request URI.
   1149             if (lastResponse.getContactHeaders() != null
   1150                     && lastResponse.getStatusCode() / 100 != 3) {
   1151                 Contact contact = (Contact) lastResponse.getContactHeaders().getFirst();
   1152                 javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI()
   1153                         .clone();
   1154                 ackRequest.setRequestURI(uri);
   1155             }
   1156             return ackRequest;
   1157         }
   1158 
   1159         ackRequest.removeHeader(RouteHeader.NAME);
   1160         RouteList routeList = new RouteList();
   1161         // start at the end of the list and walk backwards
   1162         ListIterator<RecordRoute> li = recordRouteList.listIterator(recordRouteList.size());
   1163         while (li.hasPrevious()) {
   1164             RecordRoute rr = (RecordRoute) li.previous();
   1165 
   1166             Route route = new Route();
   1167             route.setAddress((AddressImpl) ((AddressImpl) rr.getAddress()).clone());
   1168             route.setParameters((NameValueList) rr.getParameters().clone());
   1169             routeList.add(route);
   1170         }
   1171 
   1172         Contact contact = null;
   1173         if (lastResponse.getContactHeaders() != null) {
   1174             contact = (Contact) lastResponse.getContactHeaders().getFirst();
   1175         }
   1176 
   1177         if (!((SipURI) ((Route) routeList.getFirst()).getAddress().getURI()).hasLrParam()) {
   1178 
   1179             // Contact may not yet be there (bug reported by Andreas B).
   1180 
   1181             Route route = null;
   1182             if (contact != null) {
   1183                 route = new Route();
   1184                 route.setAddress((AddressImpl) ((AddressImpl) (contact.getAddress())).clone());
   1185             }
   1186 
   1187             Route firstRoute = (Route) routeList.getFirst();
   1188             routeList.removeFirst();
   1189             javax.sip.address.URI uri = firstRoute.getAddress().getURI();
   1190             ackRequest.setRequestURI(uri);
   1191 
   1192             if (route != null)
   1193                 routeList.add(route);
   1194 
   1195             ackRequest.addHeader(routeList);
   1196         } else {
   1197             if (contact != null) {
   1198                 javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI()
   1199                         .clone();
   1200                 ackRequest.setRequestURI(uri);
   1201                 ackRequest.addHeader(routeList);
   1202             }
   1203         }
   1204         return ackRequest;
   1205 
   1206     }
   1207 
   1208     /*
   1209      * Creates an ACK for an error response, according to RFC3261 section 17.1.1.3
   1210      *
   1211      * Note that this is different from an ACK for 2xx
   1212      */
   1213     private final Request createErrorAck() throws SipException, ParseException {
   1214         SIPRequest originalRequest = this.getOriginalRequest();
   1215         if (originalRequest == null)
   1216             throw new SipException("bad state " + getState());
   1217         if (!getMethod().equals(Request.INVITE)) {
   1218             throw new SipException("Can only ACK an INVITE!");
   1219         } else if (lastResponse == null) {
   1220             throw new SipException("bad Transaction state");
   1221         } else if (lastResponse.getStatusCode() < 200) {
   1222             if (sipStack.isLoggingEnabled()) {
   1223                 sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
   1224             }
   1225             throw new SipException("Cannot ACK a provisional response!");
   1226         }
   1227         return originalRequest.createErrorAck((To) lastResponse.getTo());
   1228     }
   1229 
   1230     /**
   1231      * Set the port of the recipient.
   1232      */
   1233     protected void setViaPort(int port) {
   1234         this.viaPort = port;
   1235     }
   1236 
   1237     /**
   1238      * Set the port of the recipient.
   1239      */
   1240     protected void setViaHost(String host) {
   1241         this.viaHost = host;
   1242     }
   1243 
   1244     /**
   1245      * Get the port of the recipient.
   1246      */
   1247     public int getViaPort() {
   1248         return this.viaPort;
   1249     }
   1250 
   1251     /**
   1252      * Get the host of the recipient.
   1253      */
   1254     public String getViaHost() {
   1255         return this.viaHost;
   1256     }
   1257 
   1258     /**
   1259      * get the via header for an outgoing request.
   1260      */
   1261     public Via getOutgoingViaHeader() {
   1262         return this.getMessageProcessor().getViaHeader();
   1263     }
   1264 
   1265     /**
   1266      * This is called by the stack after a non-invite client transaction goes to completed state.
   1267      */
   1268     public void clearState() {
   1269         // reduce the state to minimum
   1270         // This assumes that the application will not need
   1271         // to access the request once the transaction is
   1272         // completed.
   1273         // TODO -- revisit this - results in a null pointer
   1274         // occuring occasionally.
   1275         // this.lastRequest = null;
   1276         // this.originalRequest = null;
   1277         // this.lastResponse = null;
   1278     }
   1279 
   1280     /**
   1281      * Sets a timeout after which the connection is closed (provided the server does not use the
   1282      * connection for outgoing requests in this time period) and calls the superclass to set
   1283      * state.
   1284      */
   1285     public void setState(TransactionState newState) {
   1286         // Set this timer for connection caching
   1287         // of incoming connections.
   1288         if (newState == TransactionState.TERMINATED && this.isReliable()
   1289                 && (!getSIPStack().cacheClientConnections)) {
   1290             // Set a time after which the connection
   1291             // is closed.
   1292             this.collectionTime = TIMER_J;
   1293 
   1294         }
   1295         if (super.getState() != TransactionState.COMPLETED
   1296                 && (newState == TransactionState.COMPLETED || newState == TransactionState.TERMINATED)) {
   1297             sipStack.decrementActiveClientTransactionCount();
   1298         }
   1299         super.setState(newState);
   1300     }
   1301 
   1302     /**
   1303      * Start the timer task.
   1304      */
   1305     protected  void startTransactionTimer() {
   1306         if (this.transactionTimerStarted.compareAndSet(false, true)) {
   1307 	        TimerTask myTimer = new TransactionTimer();
   1308 	        if ( sipStack.getTimer() != null ) {
   1309 	            sipStack.getTimer().schedule(myTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL);
   1310 	        }
   1311         }
   1312     }
   1313 
   1314     /*
   1315      * Terminate a transaction. This marks the tx as terminated The tx scanner will run and remove
   1316      * the tx. (non-Javadoc)
   1317      *
   1318      * @see javax.sip.Transaction#terminate()
   1319      */
   1320     public void terminate() throws ObjectInUseException {
   1321         this.setState(TransactionState.TERMINATED);
   1322 
   1323     }
   1324 
   1325     /**
   1326      * Check if the From tag of the response matches the from tag of the original message. A
   1327      * Response with a tag mismatch should be dropped if a Dialog has been created for the
   1328      * original request.
   1329      *
   1330      * @param sipResponse the response to check.
   1331      * @return true if the check passes.
   1332      */
   1333     public boolean checkFromTag(SIPResponse sipResponse) {
   1334         String originalFromTag = ((SIPRequest) this.getRequest()).getFromTag();
   1335         if (this.defaultDialog != null) {
   1336             if (originalFromTag == null ^ sipResponse.getFrom().getTag() == null) {
   1337             	if (sipStack.isLoggingEnabled())
   1338             		sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
   1339                 return false;
   1340             }
   1341             if (originalFromTag != null
   1342                     && !originalFromTag.equalsIgnoreCase(sipResponse.getFrom().getTag())) {
   1343             	if (sipStack.isLoggingEnabled())
   1344             		sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
   1345                 return false;
   1346             }
   1347         }
   1348         return true;
   1349 
   1350     }
   1351 
   1352     /*
   1353      * (non-Javadoc)
   1354      *
   1355      * @see gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov.nist.javax.sip.message.SIPResponse,
   1356      *      gov.nist.javax.sip.stack.MessageChannel)
   1357      */
   1358     public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) {
   1359 
   1360         // If a dialog has already been created for this response,
   1361         // pass it up.
   1362         SIPDialog dialog = null;
   1363         String method = sipResponse.getCSeq().getMethod();
   1364         String dialogId = sipResponse.getDialogId(false);
   1365         if (method.equals(Request.CANCEL) && lastRequest != null) {
   1366             // JvB for CANCEL: use invite CT in CANCEL request to get dialog
   1367             // (instead of stripping tag)
   1368             SIPClientTransaction ict = (SIPClientTransaction) lastRequest.getInviteTransaction();
   1369             if (ict != null) {
   1370                 dialog = ict.defaultDialog;
   1371             }
   1372         } else {
   1373             dialog = this.getDialog(dialogId);
   1374         }
   1375 
   1376         // JvB: Check all conditions required for creating a new Dialog
   1377         if (dialog == null) {
   1378             int code = sipResponse.getStatusCode();
   1379             if ((code > 100 && code < 300)
   1380             /* skip 100 (may have a to tag */
   1381             && (sipResponse.getToTag() != null || sipStack.isRfc2543Supported())
   1382                     && sipStack.isDialogCreated(method)) {
   1383 
   1384                 /*
   1385                  * Dialog cannot be found for the response. This must be a forked response. no
   1386                  * dialog assigned to this response but a default dialog has been assigned. Note
   1387                  * that if automatic dialog support is configured then a default dialog is always
   1388                  * created.
   1389                  */
   1390 
   1391                 synchronized (this) {
   1392                     /*
   1393                      * We need synchronization here because two responses may compete for the
   1394                      * default dialog simultaneously
   1395                      */
   1396                     if (defaultDialog != null) {
   1397                         if (sipResponse.getFromTag() != null) {
   1398                             SIPResponse dialogResponse = defaultDialog.getLastResponse();
   1399                             String defaultDialogId = defaultDialog.getDialogId();
   1400                             if (dialogResponse == null
   1401                                     || (method.equals(Request.SUBSCRIBE)
   1402                                             && dialogResponse.getCSeq().getMethod().equals(
   1403                                                     Request.NOTIFY) && defaultDialogId
   1404                                             .equals(dialogId))) {
   1405                                 // The default dialog has not been claimed yet.
   1406                                 defaultDialog.setLastResponse(this, sipResponse);
   1407                                 dialog = defaultDialog;
   1408                             } else {
   1409                                 /*
   1410                                  * check if we have created one previously (happens in the case of
   1411                                  * REINVITE processing. JvB: should not happen, this.defaultDialog
   1412                                  * should then get set in Dialog#sendRequest line 1662
   1413                                  */
   1414 
   1415                                 dialog = sipStack.getDialog(dialogId);
   1416                                 if (dialog == null) {
   1417                                     if (defaultDialog.isAssigned()) {
   1418                                         /*
   1419                                          * Nop we dont have one. so go ahead and allocate a new
   1420                                          * one.
   1421                                          */
   1422                                         dialog = sipStack.createDialog(this, sipResponse);
   1423 
   1424                                     }
   1425                                 }
   1426 
   1427                             }
   1428                             if ( dialog != null ) {
   1429                                 this.setDialog(dialog, dialog.getDialogId());
   1430                             } else {
   1431                                 sipStack.getStackLogger().logError("dialog is unexpectedly null",new NullPointerException());
   1432                             }
   1433                         } else {
   1434                             throw new RuntimeException("Response without from-tag");
   1435                         }
   1436                     } else {
   1437                         // Need to create a new Dialog, this becomes default
   1438                         // JvB: not sure if this ever gets executed
   1439                         if (sipStack.isAutomaticDialogSupportEnabled) {
   1440                             dialog = sipStack.createDialog(this, sipResponse);
   1441                             this.setDialog(dialog, dialog.getDialogId());
   1442                         }
   1443                     }
   1444                 } // synchronized
   1445             } else {
   1446                 dialog = defaultDialog;
   1447             }
   1448         } else {
   1449             dialog.setLastResponse(this, sipResponse);
   1450         }
   1451         this.processResponse(sipResponse, incomingChannel, dialog);
   1452     }
   1453 
   1454     /*
   1455      * (non-Javadoc)
   1456      *
   1457      * @see gov.nist.javax.sip.stack.SIPTransaction#getDialog()
   1458      */
   1459     public  Dialog getDialog() {
   1460         // This is for backwards compatibility.
   1461         Dialog retval = null;
   1462         if (this.lastResponse != null && this.lastResponse.getFromTag() != null
   1463                 && this.lastResponse.getToTag() != null
   1464                 && this.lastResponse.getStatusCode() != 100) {
   1465             String dialogId = this.lastResponse.getDialogId(false);
   1466             retval = (Dialog) getDialog(dialogId);
   1467         }
   1468 
   1469         if (retval == null) {
   1470             retval = (Dialog) this.defaultDialog;
   1471 
   1472         }
   1473         if (sipStack.isLoggingEnabled()) {
   1474             sipStack.getStackLogger().logDebug(
   1475                     " sipDialogs =  " + sipDialogs + " default dialog " + this.defaultDialog
   1476                             + " retval " + retval);
   1477         }
   1478         return retval;
   1479 
   1480     }
   1481 
   1482     /*
   1483      * (non-Javadoc)
   1484      *
   1485      * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog,
   1486      *      gov.nist.javax.sip.message.SIPMessage)
   1487      */
   1488     public SIPDialog getDialog(String dialogId) {
   1489         SIPDialog retval = (SIPDialog) this.sipDialogs.get(dialogId);
   1490         return retval;
   1491 
   1492     }
   1493 
   1494     /*
   1495      * (non-Javadoc)
   1496      *
   1497      * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog,
   1498      *      gov.nist.javax.sip.message.SIPMessage)
   1499      */
   1500     public void setDialog(SIPDialog sipDialog, String dialogId) {
   1501         if (sipStack.isLoggingEnabled())
   1502             sipStack.getStackLogger().logDebug(
   1503                     "setDialog: " + dialogId + "sipDialog = " + sipDialog);
   1504 
   1505         if (sipDialog == null) {
   1506         	if (sipStack.isLoggingEnabled())
   1507         		sipStack.getStackLogger().logError("NULL DIALOG!!");
   1508             throw new NullPointerException("bad dialog null");
   1509         }
   1510         if (this.defaultDialog == null) {
   1511             this.defaultDialog = sipDialog;
   1512             if ( this.getMethod().equals(Request.INVITE) && this.getSIPStack().maxForkTime != 0) {
   1513                 this.getSIPStack().addForkedClientTransaction(this);
   1514             }
   1515         }
   1516         if (dialogId != null && sipDialog.getDialogId() != null) {
   1517             this.sipDialogs.put(dialogId, sipDialog);
   1518 
   1519         }
   1520 
   1521     }
   1522 
   1523     public SIPDialog getDefaultDialog() {
   1524         return this.defaultDialog;
   1525     }
   1526 
   1527     /**
   1528      * Set the next hop ( if it has already been computed).
   1529      *
   1530      * @param hop -- the hop that has been previously computed.
   1531      */
   1532     public void setNextHop(Hop hop) {
   1533         this.nextHop = hop;
   1534 
   1535     }
   1536 
   1537     /**
   1538      * Reeturn the previously computed next hop (avoid computing it twice).
   1539      *
   1540      * @return -- next hop previously computed.
   1541      */
   1542     public Hop getNextHop() {
   1543         return nextHop;
   1544     }
   1545 
   1546     /**
   1547      * Set this flag if you want your Listener to get Timeout.RETRANSMIT notifications each time a
   1548      * retransmission occurs.
   1549      *
   1550      * @param notifyOnRetransmit the notifyOnRetransmit to set
   1551      */
   1552     public void setNotifyOnRetransmit(boolean notifyOnRetransmit) {
   1553         this.notifyOnRetransmit = notifyOnRetransmit;
   1554     }
   1555 
   1556     /**
   1557      * @return the notifyOnRetransmit
   1558      */
   1559     public boolean isNotifyOnRetransmit() {
   1560         return notifyOnRetransmit;
   1561     }
   1562 
   1563     public void alertIfStillInCallingStateBy(int count) {
   1564         this.timeoutIfStillInCallingState = true;
   1565         this.callingStateTimeoutCount = count;
   1566     }
   1567 
   1568 
   1569 
   1570 }
   1571