Package test.tck.msgflow

Source Code of test.tck.msgflow.MessageFlowHarness

/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), and others.
* This software is has been contributed to the public domain.
* As a result, a formal license is not needed to use the software.
*
* This software is provided "AS IS." 
* NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
*
*/
package test.tck.msgflow;

import gov.nist.javax.sip.SipStackImpl;

import java.text.ParseException;
import java.util.LinkedList;
import java.util.List;

import javax.sip.ListeningPoint;
import javax.sip.ObjectInUseException;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.Header;
import javax.sip.header.HeaderFactory;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.ToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;

import test.tck.TckInternalError;
import test.tck.TestHarness;
import test.tck.TiUnexpectedError;

/**
* <p>
* Title: TCK
* </p>
* <p>
* Description: JAIN SIP 1.1 Technology Compatibility Kit
* </p>
*
* @author Emil Ivov Network Research Team, Louis Pasteur University,
*         Strasbourg, France
* @author Ivelin Ivanov
*
* @version 1.0
*/

public class MessageFlowHarness extends TestHarness {
  protected static final String EXTENSION_HDR = "Status-Extension";

  protected static int counter;
 
 

  // timeout values depend on pc, mine is not that powerful :)
  protected static long MESSAGES_ARRIVE_FOR = 2500;

  // it is really important to delete as a failure messes up following tests
  // so let's try real hard - 10 is a good number
  protected static int RETRY_OBJECT_DELETES = 10;

  protected static long RETRY_OBJECT_DELETES_AFTER = 500;

  protected static long STACKS_START_FOR = 1000;

  protected static long STACKS_SHUT_DOWN_FOR = 500;
 
  protected static long TRANSACTION_TIMES_OUT_FOR = 38000;

  protected ListeningPoint riListeningPoint = null;

  protected ListeningPoint tiListeningPoint = null;

  protected SipProvider riSipProvider = null;

  protected SipProvider tiSipProvider = null;

  protected SipEventCollector eventCollector = new SipEventCollector();

  protected SipStack riSipStack;

  protected SipStack tiSipStack;

  public MessageFlowHarness(String name) {
    this(name,true);
  }

  protected MessageFlowHarness(String name, boolean autoDialog) {
    super(name, autoDialog);
    System.out.println("Initializing test " + name);
   
    try {
      if ( riFactory != null)
        riFactory.resetFactory();
   
      riSipStack = riFactory.createSipStack(getRiProperties(autoDialog));
      assertTrue( "RI must be gov.nist", riSipStack instanceof SipStackImpl );
     
      tiFactory.resetFactory();
      tiFactory.setPathName( getImplementationPath() );
      tiSipStack = tiFactory.createSipStack(getTiProperties());
      if (riSipStack == tiSipStack) {
        throw new TckInternalError("riSipStack should not the same as tiSipStack");
      }
    } catch (TckInternalError ex)  {
      throw ex;
    } catch (Exception ex) {
      fail("initialization failed");
    }
  }

  // issue 17 on dev.java.net specify the headerFactory to use
  // report and fix thereof larryb@dev.java.net
  protected void addStatus(HeaderFactory headerFactory, Request request) {
    try {
      Header extension = headerFactory.createHeader(EXTENSION_HDR,
          new Integer(counter++).toString());
      request.addHeader(extension);
    } catch (ParseException ex) {
      // do nothing
    }
  }

  protected void addStatus(Request request, Response response) {
    Header extension = request.getHeader(EXTENSION_HDR);
    if (extension != null)
      response.addHeader(extension);
  }

  /**
   * Initialises both RI and TI sip stacks and stack factories.
   *
   * @throws java.lang.Exception
   *             All Let all exceptions that come from the underlying stack to
   *             pass through and surface at JUnit Level.
   */
  public void setUp() throws java.lang.Exception {

    riListeningPoint = riSipStack.createListeningPoint(LOCAL_ADDRESS, RI_PORT,
        "udp");
    riSipProvider = riSipStack.createSipProvider(riListeningPoint);

    tiListeningPoint = tiSipStack.createListeningPoint(LOCAL_ADDRESS, TI_PORT,
        "udp");
    tiSipProvider = tiSipStack.createSipProvider(tiListeningPoint);

    // If we don't wait for them to start first messages get lost and are
    // therefore reported as test failures.
    sleep(STACKS_START_FOR);
  }

  /**
   * Sets all JAIN SIP objects to null and resets the SipFactory.
   *
   * @throws java.lang.Exception
   */
  public void tearDown() throws java.lang.Exception {

   
    // Delete RI SipProvider
    int tries = 0;
    for (tries = 0; tries < RETRY_OBJECT_DELETES; tries++) {
      try {
        riSipStack.deleteSipProvider(riSipProvider);
      } catch (ObjectInUseException ex) {
        // System.err.println("Retrying delete of riSipProvider!");
        sleep(RETRY_OBJECT_DELETES_AFTER);
        continue;
      }
      break;
    }
    if (tries >= RETRY_OBJECT_DELETES)
      throw new TckInternalError("Failed to delete riSipProvider!");

    // Delete RI ListeningPoint
    for (tries = 0; tries < RETRY_OBJECT_DELETES; tries++) {
      try {
        riSipStack.deleteListeningPoint(riListeningPoint);
      } catch (ObjectInUseException ex) {
        // System.err.println("Retrying delete of riListeningPoint!");
        sleep(RETRY_OBJECT_DELETES_AFTER);
        continue;
      }
      break;
    }
    if (tries >= RETRY_OBJECT_DELETES)
      throw new TckInternalError("Failed to delete riListeningPoint!");

    riSipProvider = null;
    riListeningPoint = null;

    // Delete TI SipProvider
    for (tries = 0; tries < RETRY_OBJECT_DELETES; tries++) {
      try {
        tiSipStack.deleteSipProvider(tiSipProvider);
      } catch (ObjectInUseException ex) {
        // System.err.println("Retrying delete of tiSipProvider!");
        sleep(RETRY_OBJECT_DELETES_AFTER);
        continue;
      }
      break;
    }
    if (tries >= RETRY_OBJECT_DELETES)
      throw new TiUnexpectedError("Failed to delete tiSipProvider!");

    // Delete TI ListeningPoint
    for (tries = 0; tries < RETRY_OBJECT_DELETES; tries++) {
      try {
        tiSipStack.deleteListeningPoint(tiListeningPoint);
      } catch (ObjectInUseException ex) {
        // System.err.println("Retrying delete of tiListeningPoint!");
        sleep(RETRY_OBJECT_DELETES_AFTER);
        continue;
      }
      break;
    }

    if (tries >= RETRY_OBJECT_DELETES)
      throw new TiUnexpectedError("Failed to delete tiListeningPoint!");
    riSipStack.stop();

    tiSipStack.stop();
   

    tiSipProvider = null;
    tiListeningPoint = null;

    // Wait for stack threads to release resources (e.g. port)
    sleep(STACKS_SHUT_DOWN_FOR);
  }

  // ========================= Utility Methods =========================
  /**
   * Creates a SipRequest using the specified factories. The request has the
   * specified method and is meant to be sent from srcProvider to dstProvider.
   * This method is prefered to manual creation of requests as it helps avoid
   * using RI objects instead of corresponding TI objects (or vice versa).
   *
   * @param method
   *            the request's method
   * @param addressFactory
   *            the address factory to use when creating addresses
   * @param headerFactory
   *            the header factory to use when creating headers
   * @param messageFactory
   *            the message factory to use when creating headers
   * @param srcProvider
   *            the provider that will eventually be used to send the request
   * @param dstProvider
   *            the provider that will eventually dispatch the request to a
   *            SipListener
   * @param contentType
   *            if the content parameter is not null then this is its content
   *            type.
   * @param contentSubType
   *            if the content parameter is not null then this is its sub
   *            content type.
   * @param content
   *            the content of the request. if null this parameter is ignored
   * @return a request generated by the specified factories and destined to go
   *         from srcProvider to dstProvider
   * @throws Exception
   *             if anything should go wrong. further exception handling is
   *             left to calling methods (or JUnit).
   */
  protected Request createRequest(String method,
      AddressFactory addressFactory, HeaderFactory headerFactory,
      MessageFactory messageFactory, SipProvider srcProvider,
      SipProvider dstProvider, String contentType, String contentSubType,
      Object content) throws Exception {
    // Source SipUri
    ListeningPoint srclp = srcProvider.getListeningPoints()[0];
    SipURI srcSipURI = addressFactory.createSipURI(null, srclp
        .getIPAddress());
    srcSipURI.setPort(srclp.getPort());
    srcSipURI.setTransportParam(srclp.getTransport());

    // Destination SipURI
    ListeningPoint dstlp = dstProvider.getListeningPoints()[0];
    SipURI dstSipURI = addressFactory.createSipURI(null, dstlp
        .getIPAddress());
    dstSipURI.setPort(dstlp.getPort());
    dstSipURI.setTransportParam(dstlp.getTransport());
    // CallId
    CallIdHeader callId = srcProvider.getNewCallId();
    callId = headerFactory.createCallIdHeader( callId.getCallId() );
   
    // CSeq
    CSeqHeader cSeq = headerFactory.createCSeqHeader(1L, method);

    // From
    Address fromAddress = addressFactory.createAddress(srcSipURI);

    FromHeader from = headerFactory.createFromHeader(fromAddress, Integer
        .toString(srcProvider.hashCode()));
    // To
    Address toAddress = addressFactory.createAddress(dstSipURI);
    ToHeader to = headerFactory.createToHeader(toAddress, null);
    // Contact
    ContactHeader contact = headerFactory.createContactHeader(fromAddress);

    List via = new LinkedList();
    ViaHeader viaHeader = headerFactory.createViaHeader(srclp
        .getIPAddress(), srclp.getPort(), srclp.getTransport(),
    // BUG: Use proper RFC3261 branch ID
        "z9hG4bK" + Long.toString(System.currentTimeMillis())
    // branch id
        );
    via.add(viaHeader);
    MaxForwardsHeader maxForwards = headerFactory
        .createMaxForwardsHeader(3);

    Request request = messageFactory.createRequest(dstSipURI, method,
        callId, cSeq, from, to, via, maxForwards);
    request.addHeader(contact);
    if (contentType != null && contentSubType != null && content != null) {
      ContentTypeHeader contentTypeHdr = headerFactory
          .createContentTypeHeader(contentType, contentSubType);
      request.setContent(content, contentTypeHdr);
    }
    // pass the headerFactory - issue17 by larryb@dev.java.net
    addStatus(headerFactory, request);
    return request;
  }

  /**
   * Creates an invite request object using the RI. This invite request is
   * meant to be sent to the TI
   *
   * @param contentType
   *            if the content parameter is not null then this is its content
   *            type.
   * @param contentSubType
   *            if the content parameter is not null then this is its content
   *            sub type.
   * @param content
   *            if the request is to have any content then this parameter is
   *            used to set it. Th content parameter is to be left to null if
   *            the request won't have any content.
   * @return an RI->TI invite request
   * @throws TckInternalError
   *             if anything should gou wrong.
   */
  protected Request createRiInviteRequest(String contentType,
      String contentSubType, Object content) throws TckInternalError {
    try {
      return createRequest(Request.INVITE, riAddressFactory,
          riHeaderFactory, riMessageFactory, riSipProvider,
          tiSipProvider, contentType, contentSubType, content);
    } catch (Throwable exc) {
      throw new TckInternalError(
          "Failed to create an RI->TI invite request", exc);
    }
  }

  /**
   * Creates an invite request object using the TI. This invite request is
   * meant to be sent to the RI
   *
   * @param contentType
   *            if the content parameter is not null then this is its content
   *            type.
   * @param contentSubType
   *            if the content parameter is not null then this is its content
   *            sub type.
   * @param content
   *            if the request is to have any content then this parameter is
   *            used to set it. Th content parameter is to be left to null if
   *            the request won't have any content.
   * @return an TI->RI invite request
   * @throws TiUnexpectedError
   *             if anything should gou wrong.
   */
  protected Request createTiInviteRequest(String contentType,
      String contentSubType, Object content) throws TiUnexpectedError {
    try {
      return createRequest(Request.INVITE, tiAddressFactory,
          tiHeaderFactory, tiMessageFactory, tiSipProvider,
          riSipProvider, contentType, contentSubType, content);
    } catch (Throwable exc) {
      throw new TiUnexpectedError(
          "Failed to create a TI->RI invite request", exc);
    }
  }

  /**
   * Creates a register request object using the RI. This register request is
   * meant to be sent to the TI
   *
   * @return an RI->TI register request
   * @throws TckInternalError
   *             if anything should gou wrong.
   */
  protected Request createRiRegisterRequest() throws TckInternalError {
    try {
      return createRequest(Request.REGISTER, riAddressFactory,
          riHeaderFactory, riMessageFactory, riSipProvider,
          tiSipProvider, null, null, null);
    } catch (Throwable exc) {
      throw new TckInternalError(
          "Failed to create an RI->TI register request", exc);
    }
  }

  /**
   * Creates a register request object using the TI. This register request is
   * meant to be sent to the RI
   *
   * @return a TI->RI register request
   * @throws TiUnexpectedError
   *             if anything should gou wrong.
   */
  protected Request createTiRegisterRequest() throws TiUnexpectedError {
    try {
      return createRequest(Request.REGISTER, tiAddressFactory,
          tiHeaderFactory, tiMessageFactory, tiSipProvider,
          riSipProvider, null, null, null);

    } catch (Throwable exc) {
      throw new TiUnexpectedError(
          "Failed to create a TI->RI register request", exc);
    }
  }

  /**
   * Waits during LISTEN_TIMEOUT milliseconds. This method is called after a
   * message has been sent so that it has the time to propagate though the
   * sending and receiving stack
   */
  public static void waitForMessage() {
    sleep(MESSAGES_ARRIVE_FOR);
  }
 
  /**
   * Wait till  a transaction times out.
   *
   */
  protected static void waitForTimeout() {
    sleep(TRANSACTION_TIMES_OUT_FOR);
  }
  /**
   * waits a good long time for messages.
   */
  protected static void waitShortForMessage() {
    sleep(MESSAGES_ARRIVE_FOR/2);
  }

  /**
   * Waits during _no_less_ than sleepFor milliseconds. Had to implement it on
   * top of Thread.sleep() to guarantee minimum sleep time.
   *
   * @param sleepFor
   *            the number of miliseconds to wait
   */
  protected static void sleep(long sleepFor) {
    long startTime = System.currentTimeMillis();
    long haveBeenSleeping = 0;
    while (haveBeenSleeping < sleepFor) {
      try {
        //Thread.sleep(sleepFor - haveBeenSleeping);
        if ( sleepFor - haveBeenSleeping < 500) {
          Thread.sleep(sleepFor - haveBeenSleeping);
        } else {
          Thread.sleep(500);
          System.out.print(".");
        }
      } catch (InterruptedException ex) {
        // we-ll have to wait again!
      }
      haveBeenSleeping = (System.currentTimeMillis() - startTime);
    }

  }

  /**
   * Add a contact for the TI.
   */
  public ContactHeader createTiContact() throws Exception {
    try {
      ContactHeader contact = tiHeaderFactory.createContactHeader();

      // JvB: getIPAddress may return null!
      String ip = tiSipProvider.getSipStack().getIPAddress();
      if (ip == null) {
        ListeningPoint lp = (ListeningPoint) tiSipProvider
            .getSipStack().getListeningPoints().next();
        ip = lp.getIPAddress();
      }

      SipURI srcSipURI = tiAddressFactory.createSipURI(null, ip);
      srcSipURI.setPort(tiSipProvider.getListeningPoint("udp").getPort());
      srcSipURI.setTransportParam("udp");
      Address address = tiAddressFactory.createAddress(srcSipURI);
      address.setDisplayName("TI Contact");
      contact.setAddress(address);
      return contact;
    } catch (Exception ex) {
      ex.printStackTrace();
      assertTrue(false);
      throw ex;
    }
  }

  /**
   * Add a contact for the TI.
   */
  public ContactHeader createRiContact() throws TckInternalError {
    try {
      ContactHeader contact = riHeaderFactory.createContactHeader();
      // BUG reported by Ben Evans (Open Cloud):
      // Should be using RI's address factory here, not TI's.

      ListeningPoint lp = riSipProvider.getListeningPoints()[0];
      SipURI srcSipURI = riAddressFactory.createSipURI(null, lp
          .getIPAddress());
      srcSipURI.setPort(lp.getPort());
      srcSipURI.setTransportParam(lp.getTransport());
      Address address = riAddressFactory.createAddress(srcSipURI);
      address.setDisplayName("RI Contact");
      contact.setAddress(address);
      return contact;
    } catch (Exception ex) {
      throw new TckInternalError(ex.getMessage());
    }
  }

}
TOP

Related Classes of test.tck.msgflow.MessageFlowHarness

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.