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.