001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package gov.nist.microedition.sip;
028:
029: import javax.microedition.sip.*;
030: import java.io.OutputStream;
031: import gov.nist.microedition.sip.SipConnectionNotifierImpl;
032: import gov.nist.microedition.sip.SipClientConnectionImpl;
033: import gov.nist.siplite.SipStack;
034: import gov.nist.siplite.message.Request;
035: import gov.nist.siplite.message.Response;
036: import gov.nist.siplite.header.WWWAuthenticateHeader;
037: import gov.nist.siplite.header.AuthenticationHeader;
038: import gov.nist.siplite.stack.ClientTransaction;
039: import gov.nist.siplite.stack.MessageChannel;
040: import gov.nist.siplite.stack.Dialog;
041: import gov.nist.siplite.stack.Transaction;
042: import gov.nist.siplite.stack.SIPServerResponseInterface;
043: import gov.nist.siplite.stack.SIPStackMessageFactory;
044: import gov.nist.siplite.stack.GetSipServerResponse;
045: import gov.nist.siplite.address.Address;
046: import gov.nist.siplite.header.*;
047: import gov.nist.siplite.address.URI;
048: import gov.nist.siplite.address.SipURI;
049: import gov.nist.core.ParseException;
050: import javax.microedition.io.*;
051: import com.sun.midp.i3test.TestCase;
052: import java.io.*;
053:
054: /**
055: * Tests for initializing and sending CANCEL request.
056: *
057: */
058: public class TestSipClientCancel extends TestCase {
059:
060: /** URI of other side of SIP session (returns in 200 OK response). */
061: private String corrURI = "sip:sippy.tester@localhost:5060";
062:
063: /** Server tag. */
064: private static final String toTag = StackConnector.generateTag();
065:
066: /**
067: * Body of the test 1.
068: *
069: * Create CANCEL request and check its fields.
070: */
071: void Test1() {
072: /** Method of original request */
073: String method = "INVITE";
074: /** Client connection. */
075: SipClientConnection sc = null;
076: /**
077: * Dialog is created in case of INVITE method (RFC 3261, 12.1)
078: * or SUBSCRIBE method (RFC 3265, 3.3.4) after provisional requests.
079: */
080: try {
081: // Open SIP client connection to the local SIP server
082: sc = (SipClientConnection) Connector.open(corrURI);
083: } catch (Exception ex) {
084: assertNull("Exception during sc open", sc);
085: }
086: assertNotNull("sc is null", sc);
087: try {
088: sc.initRequest(method, null);
089: } catch (Throwable e) {
090: fail("INITIALIZED " + e + " was caused");
091: }
092:
093: // Move to PROCEEDING state
094: try {
095: sc.send();
096: } catch (Throwable e) {
097: fail("PROCEEDING " + e + " was caused");
098: }
099:
100: // new SipClientConnection instance with CANCEL request
101: SipClientConnection scCancel = null;
102: // try to create scCancel before provisional response
103: try {
104: scCancel = sc.initCancel();
105: fail("No SipException was thrown");
106: } catch (SipException e) {
107: assertTrue("Error code is wrong",
108: e.getErrorCode() == SipException.INVALID_STATE);
109: } catch (Throwable e) {
110: fail("PROCEEDING " + e + " was caused");
111: }
112:
113: // receive provisional response
114: sendResponse(sc, Response.TRYING);
115:
116: // try to create scCancel after provisional response
117: // and before final response
118: try {
119: scCancel = sc.initCancel();
120: } catch (Throwable e) {
121: fail("PROCEEDING " + e + " was caused");
122: }
123:
124: // check that scCancel != null
125: assertTrue("CANCEL connection is null", scCancel != null);
126: // check that the state of scCancel is INITIALIZED
127: // (JSR 180, initCancel method of SipClientConnection)
128: assertEquals("State is not INITIALIZED",
129: ((SipClientConnectionImpl) scCancel).getState(),
130: SipClientConnectionImpl.INITIALIZED);
131:
132: // check CANCEL request fields
133: // (RFC 3261, 9.1)
134: assertTrue("RequestURI is wrong", sc.getRequestURI()
135: .equalsIgnoreCase(scCancel.getRequestURI()));
136: assertTrue("Header Call-ID is wrong", sc.getHeader("Call-ID")
137: .equalsIgnoreCase(scCancel.getHeader("Call-ID")));
138: assertTrue("Header To is wrong", sc.getHeader("To")
139: .equalsIgnoreCase(scCancel.getHeader("To")));
140: assertTrue("Header From is wrong", sc.getHeader("From")
141: .equalsIgnoreCase(scCancel.getHeader("From")));
142: // the numeric part of CSeq MUST be equal
143: // (RFC 3261, 9.1)
144: Request originalReq = ((SipClientConnectionImpl) sc)
145: .getRequest();
146: Request cancelReq = ((SipClientConnectionImpl) scCancel)
147: .getRequest();
148: CSeqHeader originalCS = (CSeqHeader) originalReq
149: .getHeader("CSeq");
150: CSeqHeader cancelCS = (CSeqHeader) cancelReq.getHeader("CSeq");
151: assertTrue("Header CSeq is wrong", originalCS
152: .getSequenceNumber() == cancelCS.getSequenceNumber());
153: // A CANCEL constructed by a client MUST have only a single Via header
154: // field value matching the top Via value in the request
155: // being cancelled. (RFC 3261, 9.1)
156: // TBD (the situation with methods setHeader(), getHeader(),
157: // getHeaders() and removeHeader() is not clear yet
158:
159: // close connections
160: try {
161: scCancel.close();
162: } catch (Throwable e) {
163: fail("" + e + " was caused");
164: }
165:
166: // receive final response
167: sendResponse(sc, Response.OK);
168:
169: // try to create scCancel after final response
170: try {
171: scCancel = sc.initCancel();
172: fail("No SipException was thrown");
173: } catch (SipException e) {
174: assertTrue("Error code is wrong",
175: e.getErrorCode() == SipException.INVALID_STATE);
176: } catch (Throwable e) {
177: fail("PROCEEDING " + e + " was caused");
178: }
179:
180: // close connections
181: try {
182: sc.close();
183: scCancel.close();
184: } catch (Throwable e) {
185: fail("" + e + " was caused");
186: }
187:
188: }
189:
190: /**
191: * Send a response with given code.
192: *
193: * @param sc SipClientConnection object
194: * @param respCode response code
195: */
196: private void sendResponse(SipClientConnection sc, int respCode) {
197:
198: // Send a response
199: Request request = null;
200: Response response = null;
201:
202: try {
203: request = ((SipClientConnectionImpl) sc).getRequest();
204: // create a response for request
205: response = request.createResponse(respCode);
206:
207: // RFC 3261 8.2.6.2 Response must have To tag
208: ToHeader toHeader = response.getTo();
209: if (!toHeader.hasTag()) {
210: // To header has no tag - add server tag
211: toHeader.setTag(toTag);
212: response.setTo(toHeader);
213: }
214:
215: if (respCode == Response.UNAUTHORIZED) {
216: WWWAuthenticateHeader authHeader = new WWWAuthenticateHeader();
217: authHeader.setParameter(AuthenticationHeader.REALM,
218: "realm");
219: response.setHeader(authHeader);
220: }
221:
222: // add Contact header when request is not "MESSAGE"
223: if ((respCode == Response.OK)
224: && (!request.getMethod().equals("MESSAGE"))) {
225: SipURI contactURI = StackConnector.addressFactory
226: .createSipURI("sippy.tester", // name
227: "localhost:5060");
228: ContactHeader contactHeader = StackConnector.headerFactory
229: .createContactHeader(StackConnector.addressFactory
230: .createAddress(contactURI));
231: response.addHeader(contactHeader);
232: }
233:
234: ((SipClientConnectionImpl) sc).clearResponse();
235: ClientTransaction clientTransaction = ((SipClientConnectionImpl) sc)
236: .getClientTransaction();
237:
238: SipStack sipStack = ((SipClientConnectionImpl) sc)
239: .getSipStack();
240:
241: SIPServerResponseInterface ssc = GetSipServerResponse
242: .newSIPServerResponse(sipStack, response,
243: clientTransaction.getMessageChannel());
244:
245: ssc.processResponse(response, clientTransaction
246: .getMessageChannel());
247: while (((SipClientConnectionImpl) sc).getResponse() == null) {
248: Thread.yield();
249: }
250: } catch (Throwable e) {
251: fail("sendResponse " + e + " was caused");
252: }
253: }
254:
255: /**
256: * Tests execute
257: *
258: */
259: public void runTests() {
260: declare("Test CANCEL request");
261: Test1();
262: }
263:
264: }
|