/** Remove the transaction from transaction hash. */
 protected void removeTransactionHash(SIPTransaction sipTransaction) {
   SIPRequest sipRequest = sipTransaction.getOriginalRequest();
   if (sipRequest == null) return;
   if (sipTransaction instanceof SIPClientTransaction) {
     synchronized (clientTransactionTable) {
       String key = sipTransaction.getTransactionId();
       clientTransactionTable.remove(key);
     }
   } else if (sipTransaction instanceof SIPServerTransaction) {
     synchronized (serverTransactionTable) {
       String key = sipTransaction.getTransactionId();
       serverTransactionTable.remove(key);
     }
   }
 }
 /**
  * Put a dialog into the dialog table.
  *
  * @param dialog -- dialog to put into the dialog table.
  */
 public void putDialog(SIPDialog dialog) {
   String dialogId = dialog.getDialogId();
   synchronized (dialogTable) {
     if (dialogTable.containsKey(dialogId)) return;
   }
   if (LogWriter.needsLogging) {
     logWriter.logMessage("putDialog dialogId=" + dialogId);
   }
   // if (this.getDefaultRouteHeader() != null)
   //   dialog.addRoute(this.getDefaultRouteHeader(),false);
   dialog.setStack(this);
   if (LogWriter.needsLogging) logWriter.logStackTrace();
   synchronized (dialogTable) {
     dialogTable.put(dialogId, dialog);
   }
 }
  /**
   * Find the transaction corresponding to a given request.
   *
   * @param sipMessage request for which to retrieve the transaction.
   * @param isServer search the server transaction table if true.
   * @return the transaction object corresponding to the request or null if no such mapping exists.
   */
  public SIPTransaction findTransaction(SIPMessage sipMessage, boolean isServer) {
    SIPTransaction retval = null;

    if (isServer) {
      Via via = sipMessage.getTopmostVia();
      if (via.getBranch() != null) {
        String key = sipMessage.getTransactionId();

        synchronized (this.serverTransactionTable) {
          retval = (SIPTransaction) serverTransactionTable.get(key);
          if (LogWriter.needsLogging) logMessage("looking for key " + key);
          if (retval != null && retval.isMessagePartOfTransaction(sipMessage)) return retval;
        }
      }
      // Need to scan the table for old style transactions (RFC 2543
      // style)
      synchronized (this.serverTransactions) {
        Iterator<SIPServerTransaction> it = serverTransactions.iterator();
        while (it.hasNext()) {
          SIPServerTransaction sipServerTransaction = (SIPServerTransaction) it.next();
          if (sipServerTransaction.isMessagePartOfTransaction(sipMessage))
            return sipServerTransaction;
        }
      }
    } else {
      Via via = sipMessage.getTopmostVia();
      if (via.getBranch() != null) {
        String key = sipMessage.getTransactionId();
        synchronized (this.clientTransactionTable) {
          retval = (SIPTransaction) clientTransactionTable.get(key);
          if (retval != null && retval.isMessagePartOfTransaction(sipMessage)) return retval;
        }
      }
      // Need to scan the table for old style transactions (RFC 2543
      // style)
      synchronized (this.clientTransactions) {
        Iterator<SIPClientTransaction> it = clientTransactions.iterator();
        while (it.hasNext()) {
          SIPClientTransaction clientTransaction = (SIPClientTransaction) it.next();
          if (clientTransaction.isMessagePartOfTransaction(sipMessage)) return clientTransaction;
        }
      }
    }
    return null;
  }
 /** Remove transaction. */
 public void removeTransaction(SIPTransaction sipTransaction) {
   if (sipTransaction instanceof SIPServerTransaction) {
     synchronized (serverTransactions) {
       serverTransactions.remove(sipTransaction);
     }
     synchronized (serverTransactionTable) {
       String key = sipTransaction.getTransactionId();
       serverTransactionTable.remove(key);
     }
   } else {
     synchronized (clientTransactions) {
       clientTransactions.remove(sipTransaction);
     }
     synchronized (clientTransactionTable) {
       String key = sipTransaction.getTransactionId();
       clientTransactionTable.remove(key);
     }
   }
 }
 /** Hash table for quick lookup of transactions. */
 protected void addTransactionHash(SIPTransaction sipTransaction) {
   SIPRequest sipRequest = sipTransaction.getOriginalRequest();
   // Via via = sipRequest.getTopmostVia();
   // Cannot cache old style requests.
   /**
    * if (via.getBranch() == null || ! via.getBranch().toUpperCase().startsWith
    * (SIPConstants.BRANCH_MAGIC_COOKIE.toUpperCase())){ return; }
    */
   if (sipTransaction instanceof SIPClientTransaction) {
     synchronized (clientTransactionTable) {
       String key = sipRequest.getTransactionId();
       clientTransactionTable.put(key, sipTransaction);
     }
   } else {
     synchronized (serverTransactionTable) {
       String key = sipRequest.getTransactionId();
       serverTransactionTable.put(key, sipTransaction);
     }
   }
 }
  /**
   * Handles a new SIP response. It finds a client transaction to handle this message. If none
   * exists, it sends the message directly to the superclass.
   *
   * @param responseReceived Response to handle.
   * @param responseMessageChannel Channel that received message.
   * @return A client transaction.
   */
  protected ServerResponseInterface newSIPServerResponse(
      SIPResponse responseReceived, MessageChannel responseMessageChannel) {
    //	System.out.println("response = " + responseReceived.encode());

    // Iterator through all client transactions
    Iterator<SIPClientTransaction> transactionIterator;
    // Next transaction in the set
    SIPClientTransaction nextTransaction;
    // Transaction to handle this request
    SIPClientTransaction currentTransaction;

    String key = responseReceived.getTransactionId();

    currentTransaction = (SIPClientTransaction) clientTransactionTable.get(key);

    if (currentTransaction == null
        || !currentTransaction.isMessagePartOfTransaction(responseReceived)) {
      // Loop through all server transactions
      synchronized (clientTransactions) {
        transactionIterator = clientTransactions.iterator();
        currentTransaction = null;
        while (transactionIterator.hasNext() && currentTransaction == null) {

          nextTransaction = (SIPClientTransaction) transactionIterator.next();

          // If this transaction should handle this request,
          if (nextTransaction.isMessagePartOfTransaction(responseReceived)) {

            // Mark this transaction as the one to
            // handle this message
            currentTransaction = nextTransaction;
          }
        }
      }

      // If no transaction exists to handle this message,
      if (currentTransaction == null) {

        // Pass the message directly to the TU
        return super.newSIPServerResponse(responseReceived, responseMessageChannel);
      }
    }

    // Set ths transaction's encapsulated response interface
    // from the superclass
    currentTransaction.setResponseInterface(
        super.newSIPServerResponse(responseReceived, currentTransaction));
    return currentTransaction;
  }
  /**
   * Handles a new SIP request. It finds a server transaction to handle this message. If none
   * exists, it creates a new transaction.
   *
   * @param requestReceived Request to handle.
   * @param requestMessageChannel Channel that received message.
   * @return A server transaction.
   */
  protected ServerRequestInterface newSIPServerRequest(
      SIPRequest requestReceived, MessageChannel requestMessageChannel) {

    // Iterator through all server transactions
    Iterator<SIPServerTransaction> transactionIterator;
    // Next transaction in the set
    SIPServerTransaction nextTransaction;
    // Transaction to handle this request
    SIPServerTransaction currentTransaction;

    String key = requestReceived.getTransactionId();

    currentTransaction = (SIPServerTransaction) serverTransactionTable.get(key);
    if (currentTransaction == null
        || !currentTransaction.isMessagePartOfTransaction(requestReceived)) {

      // Loop through all server transactions
      synchronized (serverTransactions) {
        transactionIterator = serverTransactions.iterator();
        currentTransaction = null;
        while (transactionIterator.hasNext() && currentTransaction == null) {

          nextTransaction = (SIPServerTransaction) transactionIterator.next();

          // If this transaction should handle this request,
          if (nextTransaction.isMessagePartOfTransaction(requestReceived)) {
            // Mark this transaction as the one
            // to handle this message
            currentTransaction = nextTransaction;
          }
        }

        // If no transaction exists to handle this message
        if (currentTransaction == null) {
          currentTransaction = findPendingTransaction(requestReceived);
          if (currentTransaction != null) return currentTransaction;
          currentTransaction = createServerTransaction(requestMessageChannel);
          currentTransaction.setOriginalRequest(requestReceived);
          if (!isDialogCreated(requestReceived.getMethod())) {
            // Dialog is not created - can we find the state?
            // If so, then create a transaction and add it.
            String dialogId = requestReceived.getDialogId(true);
            SIPDialog dialog = getDialog(dialogId);
            // Sequence numbers are supposed to increment.
            // avoid processing old sequence numbers and
            // delivering the same request up to the
            // application if the request has already been seen.
            // Special handling applies to ACK processing.
            if (dialog != null
                && (requestReceived.getMethod().equals(Request.ACK)
                    || requestReceived.getCSeq().getSequenceNumber()
                        > dialog.getRemoteSequenceNumber())) {
              // Found a dialog.
              if (LogWriter.needsLogging)
                logWriter.logMessage("adding server transaction " + currentTransaction);
              serverTransactions.add(0, currentTransaction);
              addTransactionHash(currentTransaction);
              currentTransaction.startTransactionTimer();
              currentTransaction.isMapped = true;
            }
          } else {
            // Create the transaction but dont map it.
            String dialogId = requestReceived.getDialogId(true);
            SIPDialog dialog = getDialog(dialogId);
            // This is a dialog creating request that is part of an
            // existing dialog (eg. re-Invite). Re-invites get a non
            // null server transaction Id (unlike the original
            // invite).
            if (dialog != null
                && requestReceived.getCSeq().getSequenceNumber()
                    > dialog.getRemoteSequenceNumber()) {
              currentTransaction.map();
              if (LogWriter.needsLogging)
                logWriter.logMessage("adding server transaction " + currentTransaction);
              serverTransactions.add(0, currentTransaction);
              addTransactionHash(currentTransaction);
              currentTransaction.startTransactionTimer();
              currentTransaction.toListener = true;
            }
          }
        }
      }
    }

    // Set ths transaction's encapsulated request
    // interface from the superclass
    currentTransaction.setRequestInterface(
        super.newSIPServerRequest(requestReceived, currentTransaction));
    return currentTransaction;
  }
 /**
  * Return the dialog for a given dialog ID. If compatibility is enabled then we do not assume the
  * presence of tags and hence need to add a flag to indicate whether this is a server or client
  * transaction.
  *
  * @param dialogId is the dialog id to check.
  */
 public SIPDialog getDialog(String dialogId) {
   if (LogWriter.needsLogging) logWriter.logMessage("Getting dialog for " + dialogId);
   synchronized (dialogTable) {
     return (SIPDialog) dialogTable.get(dialogId);
   }
 }
 /** This is for debugging. */
 public Iterator<SIPDialog> getDialogs() {
   return dialogTable.values().iterator();
 }