FileDocCategorySizeDatePackage
TestSipClientCancel.javaAPI DocphoneME MR2 API (J2ME)9844Wed May 02 18:00:40 BST 2007gov.nist.microedition.sip

TestSipClientCancel.java

/*
 *   
 *
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */

package gov.nist.microedition.sip;

import javax.microedition.sip.*;
import java.io.OutputStream;
import gov.nist.microedition.sip.SipConnectionNotifierImpl;
import gov.nist.microedition.sip.SipClientConnectionImpl;
import gov.nist.siplite.SipStack;
import gov.nist.siplite.message.Request;
import gov.nist.siplite.message.Response;
import gov.nist.siplite.header.WWWAuthenticateHeader;
import gov.nist.siplite.header.AuthenticationHeader;
import gov.nist.siplite.stack.ClientTransaction;
import gov.nist.siplite.stack.MessageChannel;
import gov.nist.siplite.stack.Dialog;
import gov.nist.siplite.stack.Transaction;
import gov.nist.siplite.stack.SIPServerResponseInterface;
import gov.nist.siplite.stack.SIPStackMessageFactory;
import gov.nist.siplite.stack.GetSipServerResponse;
import gov.nist.siplite.address.Address;
import gov.nist.siplite.header.*;
import gov.nist.siplite.address.URI;
import gov.nist.siplite.address.SipURI;
import gov.nist.core.ParseException;
import javax.microedition.io.*;
import com.sun.midp.i3test.TestCase;
import java.io.*;

/**
 * Tests for initializing and sending CANCEL request.
 *
 */
public class TestSipClientCancel extends TestCase {
    
    /** URI of other side of SIP session (returns in 200 OK response). */
    private String corrURI = "sip:sippy.tester@localhost:5060";
    
    /** Server tag. */
    private static final String toTag = StackConnector.generateTag();

    /**
     * Body of the test 1.
     *
     * Create CANCEL request and check its fields.
     */
    void Test1() {
        /** Method of original request */
        String method = "INVITE";
        /** Client connection. */
        SipClientConnection sc = null;
        /**
         * Dialog is created in case of INVITE method (RFC 3261, 12.1)
         * or SUBSCRIBE method (RFC 3265, 3.3.4) after provisional requests.
         */
        try {
            // Open SIP client connection to the local SIP server
            sc = (SipClientConnection) 
            Connector.open(corrURI);
        } catch (Exception ex) {
            assertNull("Exception during sc open", sc);
        }
        assertNotNull("sc is null", sc);
        try {
            sc.initRequest(method, null);
        } catch (Throwable e) {
            fail("INITIALIZED " +e +" was caused");
        }
    
        // Move to PROCEEDING state
        try {
            sc.send();
        } catch (Throwable e) {
            fail("PROCEEDING " +e +" was caused");
        }

        // new SipClientConnection instance with CANCEL request
        SipClientConnection scCancel = null;
        // try to create scCancel before provisional response
        try {
            scCancel = sc.initCancel();
            fail("No SipException was thrown");
        } catch (SipException e) {
            assertTrue("Error code is wrong", 
                e.getErrorCode() == SipException.INVALID_STATE);
        } catch (Throwable e) {
            fail("PROCEEDING " +e +" was caused");
        }
        
        // receive provisional response
        sendResponse(sc, Response.TRYING);
        
        // try to create scCancel after provisional response
        // and before final response
        try {
            scCancel = sc.initCancel();
        } catch (Throwable e) {
            fail("PROCEEDING " +e +" was caused");
        }
        
        // check that scCancel != null
        assertTrue("CANCEL connection is null", scCancel != null);
        // check that the state of scCancel is INITIALIZED
        // (JSR 180, initCancel method of SipClientConnection)
        assertEquals("State is not INITIALIZED", 
            ((SipClientConnectionImpl)scCancel).getState(),
            SipClientConnectionImpl.INITIALIZED);
        
        // check CANCEL request fields
        // (RFC 3261, 9.1)
        assertTrue("RequestURI is wrong",
            sc.getRequestURI().equalsIgnoreCase(
            scCancel.getRequestURI()));
        assertTrue("Header Call-ID is wrong",
            sc.getHeader("Call-ID").equalsIgnoreCase(
            scCancel.getHeader("Call-ID")));
        assertTrue("Header To is wrong",
            sc.getHeader("To").equalsIgnoreCase(
            scCancel.getHeader("To")));
        assertTrue("Header From is wrong",
            sc.getHeader("From").equalsIgnoreCase(
            scCancel.getHeader("From")));
        // the numeric part of CSeq MUST be equal
        // (RFC 3261, 9.1)
        Request originalReq = ((SipClientConnectionImpl)sc).getRequest();
        Request cancelReq = ((SipClientConnectionImpl)scCancel).getRequest();
        CSeqHeader originalCS = (CSeqHeader)originalReq.getHeader("CSeq");
        CSeqHeader cancelCS = (CSeqHeader)cancelReq.getHeader("CSeq");
        assertTrue("Header CSeq is wrong",
            originalCS.getSequenceNumber() == cancelCS.getSequenceNumber());
        // A CANCEL constructed by a client MUST have only a single Via header
        // field value matching the top Via value in the request 
        // being cancelled. (RFC 3261, 9.1)
        // TBD (the situation with methods setHeader(), getHeader(), 
        // getHeaders() and removeHeader() is not clear yet
        
        // close connections
        try {
            scCancel.close();
        } catch (Throwable e) {
            fail("" +e +" was caused");
        }
        
        // receive final response
        sendResponse(sc, Response.OK);
        
        // try to create scCancel after final response
        try {
            scCancel = sc.initCancel();
            fail("No SipException was thrown");
        } catch (SipException e) {
            assertTrue("Error code is wrong", 
                e.getErrorCode() == SipException.INVALID_STATE);
        } catch (Throwable e) {
            fail("PROCEEDING " +e +" was caused");
        }
        
        // close connections
        try {
            sc.close();
            scCancel.close();
        } catch (Throwable e) {
            fail("" +e +" was caused");
        }
    
    }
    
    /**
     * Send a response with given code.
     *
     * @param sc SipClientConnection object
     * @param respCode response code
     */
    private void sendResponse(SipClientConnection sc, int respCode) {

        // Send a response
        Request request = null;
        Response response = null;

        try {
            request = ((SipClientConnectionImpl)sc).getRequest();
            // create a response for request
            response = request.createResponse(respCode);
            
            // RFC 3261 8.2.6.2 Response must have To tag
            ToHeader toHeader = response.getTo();
            if (!toHeader.hasTag()) {
                // To header has no tag - add server tag
                toHeader.setTag(toTag);
                response.setTo(toHeader);
            }

            if (respCode == Response.UNAUTHORIZED) {
                WWWAuthenticateHeader authHeader = new WWWAuthenticateHeader();
                authHeader.setParameter(AuthenticationHeader.REALM, "realm");
                response.setHeader(authHeader);
            }
            
            // add Contact header when request is not "MESSAGE"
            if ((respCode == Response.OK) && 
                (!request.getMethod().equals("MESSAGE"))) {
                SipURI contactURI = StackConnector
                            .addressFactory
                            .createSipURI("sippy.tester", // name
                            "localhost:5060");
                ContactHeader contactHeader =
                            StackConnector
                            .headerFactory
                            .createContactHeader(
                            StackConnector
                            .addressFactory
                            .createAddress(contactURI));
                response.addHeader(contactHeader);
            }
          
            ((SipClientConnectionImpl)sc).clearResponse();
            ClientTransaction clientTransaction = 
                ((SipClientConnectionImpl)sc).getClientTransaction();

            SipStack sipStack = ((SipClientConnectionImpl)sc).getSipStack();

            SIPServerResponseInterface ssc = 
                GetSipServerResponse.newSIPServerResponse(sipStack, response,
                clientTransaction.getMessageChannel());

            ssc.processResponse(response, 
                clientTransaction.getMessageChannel());
            while (((SipClientConnectionImpl)sc).getResponse() == null) {
                Thread.yield();
            }
        } catch (Throwable e) {
            fail("sendResponse " +e +" was caused");
        }
    }
       
    /**
     * Tests execute
     *
     */
    public void runTests() {
        declare("Test CANCEL request");
        Test1();
    }

}