0001: /*
0002: * Conditions Of Use
0003: *
0004: * This software was developed by employees of the National Institute of
0005: * Standards and Technology (NIST), and others.
0006: * This software is has been contributed to the public domain.
0007: * As a result, a formal license is not needed to use the software.
0008: *
0009: * This software is provided "AS IS."
0010: * NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
0011: * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
0012: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
0013: * AND DATA ACCURACY. NIST does not warrant or make any representations
0014: * regarding the use of the software or the results thereof, including but
0015: * not limited to the correctness, accuracy, reliability or usefulness of
0016: * the software.
0017: *
0018: *
0019: */
0020: package test.tck.msgflow;
0021:
0022: import junit.framework.*;
0023:
0024: import javax.sip.*;
0025: import javax.sip.message.*;
0026: import javax.sip.header.*;
0027: import java.util.*;
0028: import java.text.*;
0029: import test.tck.*;
0030:
0031: /**
0032: *
0033: * * The test tries to verify that Invite Server Transactions correctly change
0034: * states as specified by the rfc3261. The Reference Implementation is used
0035: * to send requests and a Tested Implementation ServerTransaction's states are
0036: * queried and compared to those in the state machine described in
0037: * section 17.2.1 of rfc3261
0038: *
0039: *<pre>
0040: *
0041: * |INVITE
0042: * |pass INV to TU
0043: * INVITE V send 100 if TU won't in 200ms
0044: * send response+-----------+
0045: * +--------| |--------+101-199 from TU
0046: * | | Proceeding| |send response
0047: * +------->| |<-------+
0048: * | | Transport Err.
0049: * | | Inform TU
0050: * | |--------------->+
0051: * +-----------+ |
0052: * 300-699 from TU | |2xx from TU |
0053: * send response | |send response |
0054: * | +------------------>+
0055: * | |
0056: * INVITE V Timer G fires |
0057: * send response+-----------+ send response |
0058: * +--------| |--------+ |
0059: * | | Completed | | |
0060: * +------->| |<-------+ |
0061: * +-----------+ |
0062: * | | |
0063: * ACK | | |
0064: * - | +------------------>+
0065: * | Timer H fires |
0066: * V or Transport Err.|
0067: * +-----------+ Inform TU |
0068: * | | |
0069: * | Confirmed | |
0070: * | | |
0071: * +-----------+ |
0072: * | |
0073: * |Timer I fires |
0074: * |- |
0075: * | |
0076: * V |
0077: * +-----------+ |
0078: * | | |
0079: * | Terminated|<---------------+
0080: * | |
0081: * +-----------+
0082: *
0083: * Figure 7: INVITE server transaction
0084: *
0085: *</pre>
0086: *
0087: * @author Emil Ivov
0088: * Network Research Team, Louis Pasteur University, Strasbourg, France.
0089: * This code is in the public domain.
0090: * @version 1.0
0091: */
0092:
0093: public class InviteServerTransactionsStateMachineTest extends
0094: MessageFlowHarness {
0095:
0096: public InviteServerTransactionsStateMachineTest(String name) {
0097: super (name);
0098: }
0099:
0100: //==================== tests ==============================
0101: /**
0102: * Tries to steer a TI server transaction through the following scenario
0103: * Proceeding-->Completed-->Confirmed-->Terminated. Apart from state
0104: * transitions, we also test, retransmissions and proper hiding/passing
0105: * of messages to the TU.
0106: */
0107: public void testProceedingCompletedConfirmedScenario() {
0108: try {
0109: Request invite = createRiInviteRequest(null, null, null);
0110: SipEventCollector responseCollector = new SipEventCollector();
0111: //Before Sending the request we should first register a listener with the
0112: //RI that would catch the TRYING response
0113: try {
0114: responseCollector.collectResponseEvent(riSipProvider);
0115: } catch (TooManyListenersException ex) {
0116: throw new TckInternalError(
0117: "Failed to register a SipListener with an RI SipProvider",
0118: ex);
0119: }
0120: //Send the initial request
0121: try {
0122: eventCollector.collectRequestEvent(tiSipProvider);
0123: riSipProvider.sendRequest(invite);
0124: } catch (SipException ex) {
0125: throw new TckInternalError(
0126: "A SipExceptionOccurred while trying to send request!",
0127: ex);
0128: } catch (TooManyListenersException ex) {
0129: throw new TiUnexpectedError(
0130: "Failed to register a SipListener with a TI SipProvider",
0131: ex);
0132: }
0133: waitForMessage();
0134: RequestEvent inviteReceivedEvent = eventCollector
0135: .extractCollectedRequestEvent();
0136: if (inviteReceivedEvent == null
0137: || inviteReceivedEvent.getRequest() == null)
0138: throw new TiUnexpectedError(
0139: "The initial invite request was not received by the TI!");
0140: //Let's create the transaction
0141: ServerTransaction tran = null;
0142: try {
0143: tran = tiSipProvider
0144: .getNewServerTransaction(inviteReceivedEvent
0145: .getRequest());
0146: } catch (Exception ex) {
0147: ex.printStackTrace();
0148: fail(ex.getClass().getName()
0149: + "was thrown while trying to "
0150: + "create the server transaction");
0151: }
0152: assertNotNull(
0153: "tiSipProvider.getNewServerTransaction() returned null",
0154: tran);
0155: //Check whether a TRYING response has been sent.
0156: //wait for the trying response
0157: waitForMessage();
0158: // At this point state must be PROCEEDING
0159: assertEquals(TransactionState.PROCEEDING, tran.getState());
0160: ResponseEvent responseEvent = responseCollector
0161: .extractCollectedResponseEvent();
0162: assertNotNull(
0163: "No TRYING response has been sent by the TI upon reception "
0164: + "of an INVITE request", responseEvent);
0165: assertTrue(
0166: "A response different from 100 was sent by the TI upon "
0167: + "reception of INVITE",
0168: Response.TRYING == responseEvent.getResponse()
0169: .getStatusCode());
0170: //Resend the invite and see that a TRYING response is resent
0171: try {
0172: //listen for the Trying response
0173: responseCollector.collectResponseEvent(riSipProvider);
0174: } catch (TooManyListenersException ex) {
0175: throw new TckInternalError(
0176: "Failed to register a SipListener with an RI SipProvider",
0177: ex);
0178: }
0179: try {
0180: eventCollector.collectRequestEvent(tiSipProvider);
0181: riSipProvider.sendRequest(invite);
0182: } catch (SipException ex) {
0183: throw new TckInternalError(
0184: "A SipExceptionOccurred while trying to send request!",
0185: ex);
0186: } catch (TooManyListenersException ex) {
0187: throw new TiUnexpectedError(
0188: "Failed to register a SipListener with a TI SipProvider",
0189: ex);
0190: }
0191: //Wait for the INVITE
0192: waitForMessage();
0193: inviteReceivedEvent = eventCollector
0194: .extractCollectedRequestEvent();
0195: assertNull(
0196: "Retransmitted INVITEs should not be passed to the TU",
0197: inviteReceivedEvent);
0198: //Wait for a retransmitted TRYING response
0199: waitForMessage();
0200: //Verify whether there was a TRYING response
0201: responseEvent = responseCollector
0202: .extractCollectedResponseEvent();
0203: assertNotNull(
0204: "No TRYING response has been sent by the TI upon reception "
0205: + "of an INVITE request", responseEvent);
0206: assertTrue(
0207: "A response different from 100 was sent by the TI upon "
0208: + "reception of INVITE",
0209: Response.TRYING == responseEvent.getResponse()
0210: .getStatusCode());
0211: //Create & send RINGING. See that it is properly sent
0212: //and that tran state doesn't change
0213: Response ringing = null;
0214: try {
0215: ringing = tiMessageFactory.createResponse(
0216: Response.RINGING, tran.getRequest());
0217: ((ToHeader) ringing.getHeader(ToHeader.NAME))
0218: .setTag(Integer.toString(hashCode()));
0219: addStatus(tran.getRequest(), ringing);
0220: // BUG report from Ben Evans:
0221: // set contact header on dialog-creating response
0222: ringing.setHeader(createTiContact());
0223: } catch (ParseException ex) {
0224: throw new TiUnexpectedError(
0225: "A ParseException was thrown while trying to create a ringing "
0226: + "response using TI", ex);
0227: }
0228: try {
0229: //listen for the RINGING response
0230: responseCollector.collectResponseEvent(riSipProvider);
0231: } catch (TooManyListenersException ex) {
0232: throw new TckInternalError(
0233: "Failed to register a SipListener with an RI SipProvider",
0234: ex);
0235: }
0236: try {
0237: tran.sendResponse(ringing);
0238: } catch (SipException ex) {
0239: ex.printStackTrace();
0240: fail("The TI failed to send a RINGING response");
0241: }
0242: //The Transaction should still be PROCEEDING
0243: assertEquals(
0244: "The Transaction did not remain PROCEEDING after transmitting a RINGING response",
0245: TransactionState.PROCEEDING, tran.getState());
0246: //Check whether the RINGING is received by the RI.
0247: waitForMessage();
0248: responseEvent = responseCollector
0249: .extractCollectedResponseEvent();
0250: assertNotNull(
0251: "The RINGING response was not received by the RI",
0252: responseEvent);
0253: assertTrue(
0254: "A response different from RINGING was sent by the TI",
0255: Response.RINGING == responseEvent.getResponse()
0256: .getStatusCode());
0257: //Resend the INVITE, see that it is hidden from the TU and see that
0258: //the _RINGING_ response is resent (and not the TRYING)
0259: try {
0260: //listen for the Trying response
0261: responseCollector.collectResponseEvent(riSipProvider);
0262: } catch (TooManyListenersException ex) {
0263: throw new TckInternalError(
0264: "Failed to register a SipListener with an RI SipProvider",
0265: ex);
0266: }
0267: try {
0268: eventCollector.collectRequestEvent(tiSipProvider);
0269: riSipProvider.sendRequest(invite);
0270: } catch (SipException ex) {
0271: throw new TckInternalError(
0272: "A SipExceptionOccurred while trying to send request!",
0273: ex);
0274: } catch (TooManyListenersException ex) {
0275: throw new TiUnexpectedError(
0276: "Failed to register a SipListener with a TI SipProvider",
0277: ex);
0278: }
0279: //Wait for the INVITE
0280: waitForMessage();
0281: inviteReceivedEvent = eventCollector
0282: .extractCollectedRequestEvent();
0283: assertNull(
0284: "Retransmitted INVITEs should not be passed to the TU",
0285: inviteReceivedEvent);
0286: //Wait for a retransmitted RINGING response
0287: waitForMessage();
0288: //Verify whether there was a RINGING response
0289: responseEvent = responseCollector
0290: .extractCollectedResponseEvent();
0291: assertNotNull(
0292: "No RINGING response has been sent by the TI upon reception "
0293: + "of an INVITE request", responseEvent);
0294: assertTrue(
0295: "A response different from RINGING was sent by the TI upon "
0296: + "reception of a retransmitted invite INVITE",
0297: Response.RINGING == responseEvent.getResponse()
0298: .getStatusCode());
0299: //We should still be proceeding
0300: assertEquals(
0301: "The server transaction left the PROCEEDING state.",
0302: TransactionState.PROCEEDING, tran.getState());
0303: //Send 300 - 699 from TU and see the tran goes COMPLETED
0304: Response busy = null;
0305: try {
0306: busy = tiMessageFactory.createResponse(
0307: Response.BUSY_HERE, tran.getRequest());
0308: addStatus(tran.getRequest(), busy);
0309: } catch (ParseException ex) {
0310: throw new TiUnexpectedError(
0311: "A ParseException was thrown while trying to create a busy_here "
0312: + "response using TI", ex);
0313: }
0314: try {
0315: //listen for the BUSY_HERE response
0316: responseCollector.collectResponseEvent(riSipProvider);
0317: } catch (TooManyListenersException ex) {
0318: throw new TckInternalError(
0319: "Failed to register a SipListener with an RI SipProvider",
0320: ex);
0321: }
0322: try {
0323: tran.sendResponse(busy);
0324: } catch (SipException ex) {
0325: ex.printStackTrace();
0326: fail("The TI failed to send a BUSY_HERE response");
0327: }
0328: //The Transaction should now be COMPLETED
0329: assertEquals(
0330: "The Transaction did not remain COMPLETED after transmitting a BUSY_HERE response",
0331: TransactionState.COMPLETED, tran.getState());
0332: //Check whether the BUSY_HERE is received by the RI.
0333: waitForMessage();
0334: responseEvent = responseCollector
0335: .extractCollectedResponseEvent();
0336: assertNotNull(
0337: "The BUSY_HERE response was not received by the RI",
0338: responseEvent);
0339: assertTrue(
0340: "A response different from BUSY_HERE was sent by the TI",
0341: Response.BUSY_HERE == responseEvent.getResponse()
0342: .getStatusCode());
0343: //Resend the initial from INVITE from the RI and see that TI
0344: //resends the 300 - 699 (see that tran state remains COMPLETED)
0345: try {
0346: //listen for the Trying response
0347: responseCollector.collectResponseEvent(riSipProvider);
0348: } catch (TooManyListenersException ex) {
0349: throw new TckInternalError(
0350: "Failed to register a SipListener with an RI SipProvider",
0351: ex);
0352: }
0353: try {
0354: eventCollector.collectRequestEvent(tiSipProvider);
0355: riSipProvider.sendRequest(invite);
0356: } catch (SipException ex) {
0357: throw new TckInternalError(
0358: "A SipExceptionOccurred while trying to send request!",
0359: ex);
0360: } catch (TooManyListenersException ex) {
0361: throw new TiUnexpectedError(
0362: "Failed to register a SipListener with a TI SipProvider",
0363: ex);
0364: }
0365: //Wait for the INVITE
0366: waitForMessage();
0367: inviteReceivedEvent = eventCollector
0368: .extractCollectedRequestEvent();
0369: assertNull(
0370: "Retransmitted INVITEs should not be passed to the TU",
0371: inviteReceivedEvent);
0372: //Wait for a retransmitted BUSY_HERE response
0373: waitForMessage();
0374: //Verify whether there was a BUSY_HERE response
0375: responseEvent = responseCollector
0376: .extractCollectedResponseEvent();
0377: assertNotNull(
0378: "No BUSY_HERE response has been sent by the TI upon reception "
0379: + "of a retransmitted INVITE request",
0380: responseEvent);
0381: assertTrue(
0382: "A response different from BUSY_HERE was sent by the TI upon "
0383: + "reception of a retransmitted invite INVITE",
0384: Response.BUSY_HERE == responseEvent.getResponse()
0385: .getStatusCode());
0386: //We should still be COMPLETED
0387: assertEquals(
0388: "The server transaction left the COMPLETED state.",
0389: TransactionState.COMPLETED, tran.getState());
0390: //Send an ack from the RI and see that the tran goes CONFIRMED
0391: //and that response retransmissions cease
0392: Request ack = (Request) invite.clone();
0393: try {
0394: eventCollector.collectRequestEvent(tiSipProvider);
0395: ack.setMethod(Request.ACK);
0396:
0397: // JvB: to tag must match response!
0398: String toTag = ((ToHeader) responseEvent.getResponse()
0399: .getHeader("to")).getTag();
0400: if (toTag != null) {
0401: ((ToHeader) ack.getHeader("to")).setTag(toTag);
0402: }
0403:
0404: riSipProvider.sendRequest(ack);
0405: } catch (TooManyListenersException ex) {
0406: throw new TiUnexpectedError(
0407: "Failed to register a SipListener with the TI provider",
0408: ex);
0409: } catch (Exception ex) {
0410: throw new TckInternalError(
0411: "Failed to create an ack request", ex);
0412: }
0413: waitForMessage();
0414: RequestEvent ackEvent = eventCollector
0415: .extractCollectedRequestEvent();
0416:
0417: assertNull(
0418: "ACKs in ServerInviteTransactions shouldn't be passed to the TU.",
0419: ackEvent);
0420: assertEquals(
0421: "The ServerTransaction did not pas into the confirmed state"
0422: + "after receiving an ACK.",
0423: TransactionState.CONFIRMED, tran.getState());
0424: } catch (Throwable exc) {
0425: exc.printStackTrace();
0426: fail(exc.getClass().getName() + ": " + exc.getMessage());
0427: }
0428: assertTrue(new Exception().getStackTrace()[0].toString(), true);
0429:
0430: }
0431:
0432: /**
0433: * JvB: tests CANCEL for an INVITE ST
0434: */
0435: public void testCanceledInvite() {
0436: try {
0437: Request invite = createRiInviteRequest(null, null, null);
0438: SipEventCollector responseCollector = new SipEventCollector();
0439: //Before Sending the request we should first register a listener with the
0440: //RI that would catch the TRYING response
0441: try {
0442: responseCollector.collectResponseEvent(riSipProvider);
0443: } catch (TooManyListenersException ex) {
0444: throw new TckInternalError(
0445: "Failed to register a SipListener with an RI SipProvider",
0446: ex);
0447: }
0448: //Send the initial request (JvB: using a CT)
0449: ClientTransaction riInviteCt;
0450: try {
0451: eventCollector.collectRequestEvent(tiSipProvider);
0452: riInviteCt = riSipProvider
0453: .getNewClientTransaction(invite);
0454: riInviteCt.sendRequest();
0455: } catch (SipException ex) {
0456: throw new TckInternalError(
0457: "A SipExceptionOccurred while trying to send request!",
0458: ex);
0459: } catch (TooManyListenersException ex) {
0460: throw new TiUnexpectedError(
0461: "Failed to register a SipListener with a TI SipProvider",
0462: ex);
0463: }
0464: waitForMessage();
0465: RequestEvent inviteReceivedEvent = eventCollector
0466: .extractCollectedRequestEvent();
0467: if (inviteReceivedEvent == null
0468: || inviteReceivedEvent.getRequest() == null)
0469: throw new TiUnexpectedError(
0470: "The initial invite request was not received by the TI!");
0471: //Let's create the transaction
0472: ServerTransaction tran = null;
0473: try {
0474: tran = tiSipProvider
0475: .getNewServerTransaction(inviteReceivedEvent
0476: .getRequest());
0477: } catch (Exception ex) {
0478: ex.printStackTrace();
0479: fail(ex.getClass().getName()
0480: + "was thrown while trying to "
0481: + "create the server transaction");
0482: }
0483: assertNotNull(
0484: "tiSipProvider.getNewServerTransaction() returned null",
0485: tran);
0486: //Check whether a TRYING response has been sent.
0487: //wait for the trying response
0488: waitForMessage();
0489: // At this point state must be PROCEEDING
0490: assertEquals(TransactionState.PROCEEDING, tran.getState());
0491: ResponseEvent responseEvent = responseCollector
0492: .extractCollectedResponseEvent();
0493: assertNotNull(
0494: "No TRYING response has been sent by the TI upon reception "
0495: + "of an INVITE request", responseEvent);
0496: assertTrue(
0497: "A response different from 100 was sent by the TI upon "
0498: + "reception of INVITE",
0499: Response.TRYING == responseEvent.getResponse()
0500: .getStatusCode());
0501:
0502: //Create & send RINGING. See that it is properly sent
0503: //and that tran state doesn't change
0504: Response ringing = null;
0505: try {
0506: ringing = tiMessageFactory.createResponse(
0507: Response.RINGING, tran.getRequest());
0508: ((ToHeader) ringing.getHeader(ToHeader.NAME))
0509: .setTag(Integer.toString(hashCode()));
0510: addStatus(tran.getRequest(), ringing);
0511: // BUG report from Ben Evans:
0512: // set contact header on dialog-creating response
0513: ringing.setHeader(createTiContact());
0514: } catch (ParseException ex) {
0515: throw new TiUnexpectedError(
0516: "A ParseException was thrown while trying to create a ringing "
0517: + "response using TI", ex);
0518: }
0519: try {
0520: //listen for the RINGING response
0521: responseCollector.collectResponseEvent(riSipProvider);
0522: } catch (TooManyListenersException ex) {
0523: throw new TckInternalError(
0524: "Failed to register a SipListener with an RI SipProvider",
0525: ex);
0526: }
0527: try {
0528: tran.sendResponse(ringing);
0529: } catch (SipException ex) {
0530: ex.printStackTrace();
0531: fail("The TI failed to send a RINGING response");
0532: }
0533: //The Transaction should still be PROCEEDING
0534: assertEquals(
0535: "The Transaction did not remain PROCEEDING after transmitting a RINGING response",
0536: TransactionState.PROCEEDING, tran.getState());
0537: //Check whether the RINGING is received by the RI.
0538: waitForMessage();
0539: responseEvent = responseCollector
0540: .extractCollectedResponseEvent();
0541: assertNotNull(
0542: "The RINGING response was not received by the RI",
0543: responseEvent);
0544: assertTrue(
0545: "A response different from RINGING was sent by the TI",
0546: Response.RINGING == responseEvent.getResponse()
0547: .getStatusCode());
0548:
0549: // JvB: *new* : send CANCEL here
0550: Request riCancel = riInviteCt.createCancel();
0551:
0552: // Send the CANCEL request
0553: try {
0554: eventCollector.collectRequestEvent(tiSipProvider);
0555: riSipProvider.sendRequest(riCancel);
0556: } catch (SipException ex) {
0557: throw new TckInternalError(
0558: "A SipExceptionOccurred while trying to send CANCEL request!",
0559: ex);
0560: } catch (TooManyListenersException ex) {
0561: throw new TiUnexpectedError(
0562: "Failed to register a SipListener with a TI SipProvider",
0563: ex);
0564: }
0565: waitForMessage();
0566: RequestEvent cancelReceivedEvent = eventCollector
0567: .extractCollectedRequestEvent();
0568: if (cancelReceivedEvent == null
0569: || cancelReceivedEvent.getRequest() == null)
0570: throw new TiUnexpectedError(
0571: "The CANCEL request was not received by the TI!");
0572:
0573: // Check that a ST was matched, and that it is equal to the INVITE ST
0574: assertEquals(tran, cancelReceivedEvent
0575: .getServerTransaction());
0576:
0577: // Send an OK to the CANCEL
0578: Response cancelOK;
0579: try {
0580: cancelOK = tiMessageFactory.createResponse(Response.OK,
0581: cancelReceivedEvent.getRequest());
0582: addStatus(cancelReceivedEvent.getRequest(), cancelOK);
0583: } catch (ParseException ex) {
0584: throw new TiUnexpectedError(
0585: "A ParseException was thrown while trying to create a OK "
0586: + "response using TI", ex);
0587: }
0588: try {
0589: //listen for the OK response
0590: responseCollector.collectResponseEvent(riSipProvider);
0591: } catch (TooManyListenersException ex) {
0592: throw new TckInternalError(
0593: "Failed to register a SipListener with an RI SipProvider",
0594: ex);
0595: }
0596: try {
0597: cancelReceivedEvent.getServerTransaction()
0598: .sendResponse(cancelOK);
0599: } catch (SipException ex) {
0600: ex.printStackTrace();
0601: fail("The TI failed to send a CANCEL OK response");
0602: }
0603:
0604: // Check whether the OK is received by the RI.
0605: waitForMessage();
0606: responseEvent = responseCollector
0607: .extractCollectedResponseEvent();
0608: assertNotNull(
0609: "The CANCEL OK response was not received by the RI",
0610: responseEvent);
0611: assertTrue(
0612: "A response different from OK was sent by the TI",
0613: Response.OK == responseEvent.getResponse()
0614: .getStatusCode());
0615:
0616: //Send 487 from TU and see the tran goes COMPLETED
0617: Response reqTerminated = null;
0618: try {
0619: reqTerminated = tiMessageFactory.createResponse(
0620: Response.REQUEST_TERMINATED, tran.getRequest());
0621: addStatus(tran.getRequest(), reqTerminated);
0622: } catch (ParseException ex) {
0623: throw new TiUnexpectedError(
0624: "A ParseException was thrown while trying to create a req_terminated "
0625: + "response using TI", ex);
0626: }
0627: try {
0628: //listen for the BUSY_HERE response
0629: responseCollector.collectResponseEvent(riSipProvider);
0630: } catch (TooManyListenersException ex) {
0631: throw new TckInternalError(
0632: "Failed to register a SipListener with an RI SipProvider",
0633: ex);
0634: }
0635: try {
0636: tran.sendResponse(reqTerminated);
0637: } catch (SipException ex) {
0638: ex.printStackTrace();
0639: fail("The TI failed to send a REQUEST_TERMINATED response");
0640: }
0641: //The Transaction should now be COMPLETED
0642: assertEquals(
0643: "The Transaction did not remain COMPLETED after transmitting a REQUEST_TERMINATED response",
0644: TransactionState.COMPLETED, tran.getState());
0645: //Check whether the BUSY_HERE is received by the RI.
0646: waitForMessage();
0647: responseEvent = responseCollector
0648: .extractCollectedResponseEvent();
0649: assertNotNull(
0650: "The REQUEST_TERMINATED response was not received by the RI",
0651: responseEvent);
0652: assertEquals(
0653: "A response different from REQUEST_TERMINATED was sent by the TI",
0654: Response.REQUEST_TERMINATED, responseEvent
0655: .getResponse().getStatusCode());
0656:
0657: // RI CT should have sent ACK, tran should be in CONFIRMED
0658: // and response retransmissions should cease
0659: assertEquals(
0660: "The ServerTransaction did not pas into the confirmed state"
0661: + "after receiving an ACK.",
0662: TransactionState.CONFIRMED, tran.getState());
0663: } catch (Throwable exc) {
0664: exc.printStackTrace();
0665: fail(exc.getClass().getName() + ": " + exc.getMessage());
0666: }
0667: assertTrue(new Exception().getStackTrace()[0].toString(), true);
0668:
0669: }
0670:
0671: /**
0672: * JvB: tests CANCEL for an INVITE ST, from an non-RFC3261 client
0673: * which uses a Via branch not starting with the magic cookie
0674: */
0675: public void testNonRFC3261CanceledInvite() {
0676: try {
0677: Request invite = createRiInviteRequest(null, null, null);
0678:
0679: // JvB: Pretend it is sent by an older client
0680: ViaHeader topVia = (ViaHeader) invite.getHeader("Via");
0681: topVia.setBranch("non-rfc3261");
0682:
0683: SipEventCollector responseCollector = new SipEventCollector();
0684: //Before Sending the request we should first register a listener with the
0685: //RI that would catch the TRYING response
0686: try {
0687: responseCollector.collectResponseEvent(riSipProvider);
0688: } catch (TooManyListenersException ex) {
0689: throw new TckInternalError(
0690: "Failed to register a SipListener with an RI SipProvider",
0691: ex);
0692: }
0693: //Send the initial request (JvB: using a CT)
0694: ClientTransaction riInviteCt;
0695: try {
0696: eventCollector.collectRequestEvent(tiSipProvider);
0697: riInviteCt = riSipProvider
0698: .getNewClientTransaction(invite);
0699: riInviteCt.sendRequest();
0700: } catch (SipException ex) {
0701: throw new TckInternalError(
0702: "A SipExceptionOccurred while trying to send request!",
0703: ex);
0704: } catch (TooManyListenersException ex) {
0705: throw new TiUnexpectedError(
0706: "Failed to register a SipListener with a TI SipProvider",
0707: ex);
0708: }
0709: waitForMessage();
0710: RequestEvent inviteReceivedEvent = eventCollector
0711: .extractCollectedRequestEvent();
0712: if (inviteReceivedEvent == null
0713: || inviteReceivedEvent.getRequest() == null)
0714: throw new TiUnexpectedError(
0715: "The initial invite request was not received by the TI!");
0716: //Let's create the transaction
0717: ServerTransaction tran = null;
0718: try {
0719: tran = tiSipProvider
0720: .getNewServerTransaction(inviteReceivedEvent
0721: .getRequest());
0722: } catch (Exception ex) {
0723: ex.printStackTrace();
0724: fail(ex.getClass().getName()
0725: + "was thrown while trying to "
0726: + "create the server transaction");
0727: }
0728: assertNotNull(
0729: "tiSipProvider.getNewServerTransaction() returned null",
0730: tran);
0731: //Check whether a TRYING response has been sent.
0732: //wait for the trying response
0733: waitForMessage();
0734: // At this point state must be PROCEEDING
0735: assertEquals(TransactionState.PROCEEDING, tran.getState());
0736: ResponseEvent responseEvent = responseCollector
0737: .extractCollectedResponseEvent();
0738: assertNotNull(
0739: "No TRYING response has been sent by the TI upon reception "
0740: + "of an INVITE request", responseEvent);
0741: assertTrue(
0742: "A response different from 100 was sent by the TI upon "
0743: + "reception of INVITE",
0744: Response.TRYING == responseEvent.getResponse()
0745: .getStatusCode());
0746:
0747: //Create & send RINGING. See that it is properly sent
0748: //and that tran state doesn't change
0749: Response ringing = null;
0750: try {
0751: ringing = tiMessageFactory.createResponse(
0752: Response.RINGING, tran.getRequest());
0753: ((ToHeader) ringing.getHeader(ToHeader.NAME))
0754: .setTag(Integer.toString(hashCode()));
0755: addStatus(tran.getRequest(), ringing);
0756: // BUG report from Ben Evans:
0757: // set contact header on dialog-creating response
0758: ringing.setHeader(createTiContact());
0759: } catch (ParseException ex) {
0760: throw new TiUnexpectedError(
0761: "A ParseException was thrown while trying to create a ringing "
0762: + "response using TI", ex);
0763: }
0764: try {
0765: //listen for the RINGING response
0766: responseCollector.collectResponseEvent(riSipProvider);
0767: } catch (TooManyListenersException ex) {
0768: throw new TckInternalError(
0769: "Failed to register a SipListener with an RI SipProvider",
0770: ex);
0771: }
0772: try {
0773: tran.sendResponse(ringing);
0774: } catch (SipException ex) {
0775: ex.printStackTrace();
0776: fail("The TI failed to send a RINGING response");
0777: }
0778: //The Transaction should still be PROCEEDING
0779: assertEquals(
0780: "The Transaction did not remain PROCEEDING after transmitting a RINGING response",
0781: TransactionState.PROCEEDING, tran.getState());
0782: //Check whether the RINGING is received by the RI.
0783: waitForMessage();
0784: responseEvent = responseCollector
0785: .extractCollectedResponseEvent();
0786: assertNotNull(
0787: "The RINGING response was not received by the RI",
0788: responseEvent);
0789: assertTrue(
0790: "A response different from RINGING was sent by the TI",
0791: Response.RINGING == responseEvent.getResponse()
0792: .getStatusCode());
0793:
0794: // JvB: *new* : send CANCEL here
0795: Request riCancel = riInviteCt.createCancel();
0796:
0797: // Send the CANCEL request
0798: try {
0799: eventCollector.collectRequestEvent(tiSipProvider);
0800: riSipProvider.sendRequest(riCancel);
0801: } catch (SipException ex) {
0802: throw new TckInternalError(
0803: "A SipExceptionOccurred while trying to send CANCEL request!",
0804: ex);
0805: } catch (TooManyListenersException ex) {
0806: throw new TiUnexpectedError(
0807: "Failed to register a SipListener with a TI SipProvider",
0808: ex);
0809: }
0810: waitForMessage();
0811: RequestEvent cancelReceivedEvent = eventCollector
0812: .extractCollectedRequestEvent();
0813: if (cancelReceivedEvent == null
0814: || cancelReceivedEvent.getRequest() == null)
0815: throw new TiUnexpectedError(
0816: "The CANCEL request was not received by the TI!");
0817:
0818: // Check that a ST was matched, and that it is equal to the INVITE ST
0819: assertEquals(tran, cancelReceivedEvent
0820: .getServerTransaction());
0821:
0822: // Send an OK to the CANCEL
0823: Response cancelOK;
0824: try {
0825: cancelOK = tiMessageFactory.createResponse(Response.OK,
0826: cancelReceivedEvent.getRequest());
0827: addStatus(cancelReceivedEvent.getRequest(), cancelOK);
0828: } catch (ParseException ex) {
0829: throw new TiUnexpectedError(
0830: "A ParseException was thrown while trying to create a OK "
0831: + "response using TI", ex);
0832: }
0833: try {
0834: //listen for the OK response
0835: responseCollector.collectResponseEvent(riSipProvider);
0836: } catch (TooManyListenersException ex) {
0837: throw new TckInternalError(
0838: "Failed to register a SipListener with an RI SipProvider",
0839: ex);
0840: }
0841: try {
0842: // send it statelessly
0843: cancelReceivedEvent.getServerTransaction()
0844: .sendResponse(cancelOK);
0845: } catch (SipException ex) {
0846: ex.printStackTrace();
0847: fail("The TI failed to send a CANCEL OK response");
0848: }
0849:
0850: // Check whether the OK is received by the RI.
0851: waitForMessage();
0852: responseEvent = responseCollector
0853: .extractCollectedResponseEvent();
0854: assertNotNull(
0855: "The CANCEL OK response was not received by the RI",
0856: responseEvent);
0857: assertTrue(
0858: "A response different from OK was sent by the TI",
0859: Response.OK == responseEvent.getResponse()
0860: .getStatusCode());
0861:
0862: //Send 487 from TU and see the tran goes COMPLETED
0863: Response reqTerminated = null;
0864: try {
0865: reqTerminated = tiMessageFactory.createResponse(
0866: Response.REQUEST_TERMINATED, tran.getRequest());
0867: addStatus(tran.getRequest(), reqTerminated);
0868: } catch (ParseException ex) {
0869: throw new TiUnexpectedError(
0870: "A ParseException was thrown while trying to create a req_terminated "
0871: + "response using TI", ex);
0872: }
0873: try {
0874: //listen for the BUSY_HERE response
0875: responseCollector.collectResponseEvent(riSipProvider);
0876: } catch (TooManyListenersException ex) {
0877: throw new TckInternalError(
0878: "Failed to register a SipListener with an RI SipProvider",
0879: ex);
0880: }
0881: try {
0882: tran.sendResponse(reqTerminated);
0883: } catch (SipException ex) {
0884: ex.printStackTrace();
0885: fail("The TI failed to send a REQUEST_TERMINATED response");
0886: }
0887: //The Transaction should now be COMPLETED
0888: assertEquals(
0889: "The Transaction did not remain COMPLETED after transmitting a REQUEST_TERMINATED response",
0890: TransactionState.COMPLETED, tran.getState());
0891: //Check whether the BUSY_HERE is received by the RI.
0892: waitForMessage();
0893: responseEvent = responseCollector
0894: .extractCollectedResponseEvent();
0895: assertNotNull(
0896: "The REQUEST_TERMINATED response was not received by the RI",
0897: responseEvent);
0898: assertTrue(
0899: "A response different from REQUEST_TERMINATED was sent by the TI",
0900: Response.REQUEST_TERMINATED == responseEvent
0901: .getResponse().getStatusCode());
0902:
0903: // RI CT should have sent ACK, tran should be in CONFIRMED
0904: // and response retransmissions should cease
0905: assertEquals(
0906: "The ServerTransaction did not pas into the confirmed state"
0907: + "after receiving an ACK.",
0908: TransactionState.CONFIRMED, tran.getState());
0909: } catch (Throwable exc) {
0910: exc.printStackTrace();
0911: fail(exc.getClass().getName() + ": " + exc.getMessage());
0912: }
0913: assertTrue(new Exception().getStackTrace()[0].toString(), true);
0914:
0915: }
0916:
0917: /**
0918: * JvB: tests CANCEL for an INVITE ST, in case the client changes
0919: * the case of the branch id to all lowercvase (NIST used to do this)
0920: */
0921: public void testCaseInsensitiveCanceledInvite() {
0922: try {
0923: Request invite = createRiInviteRequest(null, null, null);
0924: SipEventCollector responseCollector = new SipEventCollector();
0925: //Before Sending the request we should first register a listener with the
0926: //RI that would catch the TRYING response
0927: try {
0928: responseCollector.collectResponseEvent(riSipProvider);
0929: } catch (TooManyListenersException ex) {
0930: throw new TckInternalError(
0931: "Failed to register a SipListener with an RI SipProvider",
0932: ex);
0933: }
0934: //Send the initial request (JvB: using a CT)
0935: ClientTransaction riInviteCt;
0936: try {
0937: eventCollector.collectRequestEvent(tiSipProvider);
0938: riInviteCt = riSipProvider
0939: .getNewClientTransaction(invite);
0940: riInviteCt.sendRequest();
0941: } catch (SipException ex) {
0942: throw new TckInternalError(
0943: "A SipExceptionOccurred while trying to send request!",
0944: ex);
0945: } catch (TooManyListenersException ex) {
0946: throw new TiUnexpectedError(
0947: "Failed to register a SipListener with a TI SipProvider",
0948: ex);
0949: }
0950: waitForMessage();
0951: RequestEvent inviteReceivedEvent = eventCollector
0952: .extractCollectedRequestEvent();
0953: if (inviteReceivedEvent == null
0954: || inviteReceivedEvent.getRequest() == null)
0955: throw new TiUnexpectedError(
0956: "The initial invite request was not received by the TI!");
0957: //Let's create the transaction
0958: ServerTransaction tran = null;
0959: try {
0960: tran = tiSipProvider
0961: .getNewServerTransaction(inviteReceivedEvent
0962: .getRequest());
0963: } catch (Exception ex) {
0964: ex.printStackTrace();
0965: fail(ex.getClass().getName()
0966: + "was thrown while trying to "
0967: + "create the server transaction");
0968: }
0969: assertNotNull(
0970: "tiSipProvider.getNewServerTransaction() returned null",
0971: tran);
0972: //Check whether a TRYING response has been sent.
0973: //wait for the trying response
0974: waitForMessage();
0975: // At this point state must be PROCEEDING
0976: assertEquals(TransactionState.PROCEEDING, tran.getState());
0977: ResponseEvent responseEvent = responseCollector
0978: .extractCollectedResponseEvent();
0979: assertNotNull(
0980: "No TRYING response has been sent by the TI upon reception "
0981: + "of an INVITE request", responseEvent);
0982: assertTrue(
0983: "A response different from 100 was sent by the TI upon "
0984: + "reception of INVITE",
0985: Response.TRYING == responseEvent.getResponse()
0986: .getStatusCode());
0987:
0988: //Create & send RINGING. See that it is properly sent
0989: //and that tran state doesn't change
0990: Response ringing = null;
0991: try {
0992: ringing = tiMessageFactory.createResponse(
0993: Response.RINGING, tran.getRequest());
0994: ((ToHeader) ringing.getHeader(ToHeader.NAME))
0995: .setTag(Integer.toString(hashCode()));
0996: addStatus(tran.getRequest(), ringing);
0997: // BUG report from Ben Evans:
0998: // set contact header on dialog-creating response
0999: ringing.setHeader(createTiContact());
1000: } catch (ParseException ex) {
1001: throw new TiUnexpectedError(
1002: "A ParseException was thrown while trying to create a ringing "
1003: + "response using TI", ex);
1004: }
1005: try {
1006: //listen for the RINGING response
1007: responseCollector.collectResponseEvent(riSipProvider);
1008: } catch (TooManyListenersException ex) {
1009: throw new TckInternalError(
1010: "Failed to register a SipListener with an RI SipProvider",
1011: ex);
1012: }
1013: try {
1014: tran.sendResponse(ringing);
1015: } catch (SipException ex) {
1016: ex.printStackTrace();
1017: fail("The TI failed to send a RINGING response");
1018: }
1019: //The Transaction should still be PROCEEDING
1020: assertEquals(
1021: "The Transaction did not remain PROCEEDING after transmitting a RINGING response",
1022: TransactionState.PROCEEDING, tran.getState());
1023: //Check whether the RINGING is received by the RI.
1024: waitForMessage();
1025: responseEvent = responseCollector
1026: .extractCollectedResponseEvent();
1027: assertNotNull(
1028: "The RINGING response was not received by the RI",
1029: responseEvent);
1030: assertTrue(
1031: "A response different from RINGING was sent by the TI",
1032: Response.RINGING == responseEvent.getResponse()
1033: .getStatusCode());
1034:
1035: // JvB: *new* : send CANCEL here
1036: Request riCancel = riInviteCt.createCancel();
1037:
1038: // Change Via branch to all lower case, clients SHOULD NOT
1039: // do this but stack should be able to handle this
1040: ViaHeader topVia = (ViaHeader) riCancel.getHeader("Via");
1041: topVia.setBranch(topVia.getBranch().toLowerCase());
1042:
1043: // Send the CANCEL request
1044: try {
1045: eventCollector.collectRequestEvent(tiSipProvider);
1046: riSipProvider.sendRequest(riCancel);
1047: } catch (SipException ex) {
1048: throw new TckInternalError(
1049: "A SipExceptionOccurred while trying to send CANCEL request!",
1050: ex);
1051: } catch (TooManyListenersException ex) {
1052: throw new TiUnexpectedError(
1053: "Failed to register a SipListener with a TI SipProvider",
1054: ex);
1055: }
1056: waitForMessage();
1057: RequestEvent cancelReceivedEvent = eventCollector
1058: .extractCollectedRequestEvent();
1059: if (cancelReceivedEvent == null
1060: || cancelReceivedEvent.getRequest() == null)
1061: throw new TiUnexpectedError(
1062: "The CANCEL request was not received by the TI!");
1063:
1064: // Check that a ST was matched, and that it is equal to the INVITE ST
1065: // mranga -- I dont know if its valid to do things this way!
1066: //assertSame( tran, cancelReceivedEvent.getServerTransaction() );
1067:
1068: // Send an OK to the CANCEL
1069: Response cancelOK;
1070: try {
1071: cancelOK = tiMessageFactory.createResponse(Response.OK,
1072: cancelReceivedEvent.getRequest());
1073: addStatus(cancelReceivedEvent.getRequest(), cancelOK);
1074: } catch (ParseException ex) {
1075: throw new TiUnexpectedError(
1076: "A ParseException was thrown while trying to create a OK "
1077: + "response using TI", ex);
1078: }
1079: try {
1080: //listen for the OK response
1081: responseCollector.collectResponseEvent(riSipProvider);
1082: } catch (TooManyListenersException ex) {
1083: throw new TckInternalError(
1084: "Failed to register a SipListener with an RI SipProvider",
1085: ex);
1086: }
1087: try {
1088:
1089: cancelReceivedEvent.getServerTransaction()
1090: .sendResponse(cancelOK);
1091: } catch (SipException ex) {
1092: ex.printStackTrace();
1093: fail("The TI failed to send a CANCEL OK response");
1094: }
1095:
1096: // Check whether the OK is received by the RI.
1097: waitForMessage();
1098: responseEvent = responseCollector
1099: .extractCollectedResponseEvent();
1100: assertNotNull(
1101: "The CANCEL OK response was not received by the RI",
1102: responseEvent);
1103: assertTrue(
1104: "A response different from OK was sent by the TI",
1105: Response.OK == responseEvent.getResponse()
1106: .getStatusCode());
1107:
1108: //Send 487 from TU and see the tran goes COMPLETED
1109: Response reqTerminated = null;
1110: try {
1111: reqTerminated = tiMessageFactory.createResponse(
1112: Response.REQUEST_TERMINATED, tran.getRequest());
1113: addStatus(tran.getRequest(), reqTerminated);
1114: } catch (ParseException ex) {
1115: throw new TiUnexpectedError(
1116: "A ParseException was thrown while trying to create a req_terminated "
1117: + "response using TI", ex);
1118: }
1119: try {
1120: //listen for the BUSY_HERE response
1121: responseCollector.collectResponseEvent(riSipProvider);
1122: } catch (TooManyListenersException ex) {
1123: throw new TckInternalError(
1124: "Failed to register a SipListener with an RI SipProvider",
1125: ex);
1126: }
1127: try {
1128: tran.sendResponse(reqTerminated);
1129: } catch (SipException ex) {
1130: ex.printStackTrace();
1131: fail("The TI failed to send a REQUEST_TERMINATED response");
1132: }
1133: //The Transaction should now be COMPLETED
1134: assertEquals(
1135: "The Transaction did not remain COMPLETED after transmitting a REQUEST_TERMINATED response",
1136: TransactionState.COMPLETED, tran.getState());
1137: //Check whether the BUSY_HERE is received by the RI.
1138: waitShortForMessage();
1139: responseEvent = responseCollector
1140: .extractCollectedResponseEvent();
1141: assertNotNull(
1142: "The REQUEST_TERMINATED response was not received by the RI",
1143: responseEvent);
1144: assertTrue(
1145: "A response different from REQUEST_TERMINATED was sent by the TI",
1146: Response.REQUEST_TERMINATED == responseEvent
1147: .getResponse().getStatusCode());
1148:
1149: // RI CT should have sent ACK, tran should be in CONFIRMED
1150: // and response retransmissions should cease
1151:
1152: assertEquals(
1153: "The ServerTransaction did not pas into the confirmed state"
1154: + "after receiving an ACK.",
1155: TransactionState.CONFIRMED, tran.getState());
1156: } catch (Throwable exc) {
1157: exc.printStackTrace();
1158: fail(exc.getClass().getName() + ": " + exc.getMessage());
1159: }
1160: assertTrue(new Exception().getStackTrace()[0].toString(), true);
1161:
1162: }
1163:
1164: /**
1165: * Tries to steer a TI server transaction through the following scenario
1166: * Proceeding-->Terminated. Apart from state transitions, we also test,
1167: * retransmissions and proper hiding/passing of messages to the TU.
1168: */
1169: public void testProceedingTerminatedScenario() {
1170: try {
1171: Request invite = createRiInviteRequest(null, null, null);
1172: SipEventCollector responseCollector = new SipEventCollector();
1173: //Before Sending the request we should first register a listener with the
1174: //RI that would catch the TRYING response
1175: try {
1176: responseCollector.collectResponseEvent(riSipProvider);
1177: } catch (TooManyListenersException ex) {
1178: throw new TckInternalError(
1179: "Failed to register a SipListener with an RI SipProvider",
1180: ex);
1181: }
1182: //Send the initial request
1183: //riSipProvider.setAutomaticDialogSupportEnabled(false);
1184: try {
1185: eventCollector.collectRequestEvent(tiSipProvider);
1186: riSipProvider.sendRequest(invite);
1187: } catch (SipException ex) {
1188: throw new TckInternalError(
1189: "A SipExceptionOccurred while trying to send request!",
1190: ex);
1191: } catch (TooManyListenersException ex) {
1192: throw new TiUnexpectedError(
1193: "Failed to register a SipListener with a TI SipProvider",
1194: ex);
1195: }
1196: waitForMessage();
1197: RequestEvent inviteReceivedEvent = eventCollector
1198: .extractCollectedRequestEvent();
1199: if (inviteReceivedEvent == null
1200: || inviteReceivedEvent.getRequest() == null)
1201: throw new TiUnexpectedError(
1202: "The initial invite request was not received by the TI!");
1203: //Let's create the transaction
1204: ServerTransaction tran = null;
1205: try {
1206: tran = tiSipProvider
1207: .getNewServerTransaction(inviteReceivedEvent
1208: .getRequest());
1209: } catch (Exception ex) {
1210: ex.printStackTrace();
1211: fail(ex.getClass().getName()
1212: + "was thrown while trying to "
1213: + "create the server transaction");
1214: }
1215: assertNotNull(
1216: "tiSipProvider.getNewServerTransaction() returned null",
1217: tran);
1218: //Check whether a TRYING response has been sent.
1219: //wait for the trying response
1220: waitForMessage();
1221: // State must be proceeding After Response has been sent.
1222: assertEquals(TransactionState.PROCEEDING, tran.getState());
1223: ResponseEvent responseEvent = responseCollector
1224: .extractCollectedResponseEvent();
1225: assertNotNull(
1226: "No TRYING response has been sent by the TI upon reception "
1227: + "of an INVITE request", responseEvent);
1228: assertTrue(
1229: "A response different from 100 was sent by the TI upon "
1230: + "reception of INVITE",
1231: Response.TRYING == responseEvent.getResponse()
1232: .getStatusCode());
1233: //Resend the invite and see that a TRYING response is resent
1234: try {
1235: //listen for the Trying response
1236: responseCollector.collectResponseEvent(riSipProvider);
1237: } catch (TooManyListenersException ex) {
1238: throw new TckInternalError(
1239: "Failed to register a SipListener with an RI SipProvider",
1240: ex);
1241: }
1242: try {
1243: eventCollector.collectRequestEvent(tiSipProvider);
1244: riSipProvider.sendRequest(invite);
1245: } catch (SipException ex) {
1246: throw new TckInternalError(
1247: "A SipExceptionOccurred while trying to send request!",
1248: ex);
1249: } catch (TooManyListenersException ex) {
1250: throw new TiUnexpectedError(
1251: "Failed to register a SipListener with a TI SipProvider",
1252: ex);
1253: }
1254: //Wait for the INVITE
1255: waitForMessage();
1256: inviteReceivedEvent = eventCollector
1257: .extractCollectedRequestEvent();
1258: assertNull(
1259: "Retransmitted INVITEs should not be passed to the TU",
1260: inviteReceivedEvent);
1261: //Wait for a retransmitted TRYING response
1262: waitForMessage();
1263: //Verify whether there was a TRYING response
1264: responseEvent = responseCollector
1265: .extractCollectedResponseEvent();
1266: assertNotNull(
1267: "No TRYING response has been sent by the TI upon reception "
1268: + "of an INVITE request", responseEvent);
1269: assertTrue(
1270: "A response different from 100 was sent by the TI upon "
1271: + "reception of INVITE",
1272: Response.TRYING == responseEvent.getResponse()
1273: .getStatusCode());
1274: //Create & send RINGING. See that it is properly sent
1275: //and that tran state doesn't change
1276: Response ringing = null;
1277: try {
1278: ringing = tiMessageFactory.createResponse(
1279: Response.RINGING, tran.getRequest());
1280: ((ToHeader) ringing.getHeader(ToHeader.NAME))
1281: .setTag(Integer.toString(hashCode()));
1282: addStatus(tran.getRequest(), ringing);
1283: // BUG report from Ben Evans:
1284: // set contact header on dialog-creating response
1285: ringing.setHeader(createTiContact());
1286: } catch (ParseException ex) {
1287: throw new TiUnexpectedError(
1288: "A ParseException was thrown while trying to create a ringing "
1289: + "response using TI", ex);
1290: }
1291: try {
1292: //listen for the RINGING response
1293: responseCollector.collectResponseEvent(riSipProvider);
1294: } catch (TooManyListenersException ex) {
1295: throw new TckInternalError(
1296: "Failed to register a SipListener with an RI SipProvider",
1297: ex);
1298: }
1299: try {
1300: tran.sendResponse(ringing);
1301: } catch (SipException ex) {
1302: ex.printStackTrace();
1303: fail("The TI failed to send a RINGING response");
1304: }
1305: //The Transaction should still be PROCEEDING
1306: assertEquals(
1307: "The Transaction did not remain PROCEEDING after transmitting a RINGING response",
1308: TransactionState.PROCEEDING, tran.getState());
1309: //Check whether the RINGING is received by the RI.
1310: waitForMessage();
1311: responseEvent = responseCollector
1312: .extractCollectedResponseEvent();
1313: assertNotNull(
1314: "The RINGING response was not received by the RI",
1315: responseEvent);
1316: assertTrue(
1317: "A response different from RINGING was sent by the TI",
1318: Response.RINGING == responseEvent.getResponse()
1319: .getStatusCode());
1320: //Resend the INVITE, see that it is hidden from the TU and see that
1321: //the _RINGING_ response is resent (and not the TRYING)
1322: try {
1323: //listen for the Trying response
1324: responseCollector.collectResponseEvent(riSipProvider);
1325: } catch (TooManyListenersException ex) {
1326: throw new TckInternalError(
1327: "Failed to register a SipListener with an RI SipProvider",
1328: ex);
1329: }
1330: try {
1331: eventCollector.collectRequestEvent(tiSipProvider);
1332: riSipProvider.sendRequest(invite);
1333: } catch (SipException ex) {
1334: throw new TckInternalError(
1335: "A SipExceptionOccurred while trying to send request!",
1336: ex);
1337: } catch (TooManyListenersException ex) {
1338: throw new TiUnexpectedError(
1339: "Failed to register a SipListener with a TI SipProvider",
1340: ex);
1341: }
1342: //Wait for the INVITE
1343: waitForMessage();
1344: inviteReceivedEvent = eventCollector
1345: .extractCollectedRequestEvent();
1346: assertNull(
1347: "Retransmitted INVITEs should not be passed to the TU",
1348: inviteReceivedEvent);
1349: //Wait for a retransmitted RINGING response
1350: waitForMessage();
1351: //Verify whether there was a RINGING response
1352: responseEvent = responseCollector
1353: .extractCollectedResponseEvent();
1354: assertNotNull(
1355: "No RINGING response has been sent by the TI upon reception "
1356: + "of an INVITE request", responseEvent);
1357: assertTrue(
1358: "A response different from RINGING was sent by the TI upon "
1359: + "reception of a retransmitted invite INVITE",
1360: Response.RINGING == responseEvent.getResponse()
1361: .getStatusCode());
1362: //We should still be proceeding
1363: assertEquals(
1364: "The server transaction left the PROCEEDING state.",
1365: TransactionState.PROCEEDING, tran.getState());
1366: //Create a 2xx final response and test transaction termination
1367: Response ok = null;
1368: try {
1369: ok = tiMessageFactory.createResponse(Response.OK, tran
1370: .getRequest());
1371: ContactHeader contact = this .createTiContact();
1372: ok.addHeader(contact);
1373: ((ToHeader) ok.getHeader(ToHeader.NAME)).setTag(Integer
1374: .toString(hashCode()));
1375: addStatus(tran.getRequest(), ok);
1376: } catch (ParseException ex) {
1377: throw new TiUnexpectedError(
1378: "A ParseException was thrown while trying to create an ok "
1379: + "response using TI", ex);
1380: }
1381: try {
1382: //listen for the OK response
1383: responseCollector.collectResponseEvent(riSipProvider);
1384: } catch (TooManyListenersException ex) {
1385: throw new TckInternalError(
1386: "Failed to register a SipListener with an RI SipProvider",
1387: ex);
1388: }
1389: try {
1390: tran.sendResponse(ok);
1391: } catch (SipException ex) {
1392: ex.printStackTrace();
1393: fail("The TI failed to send a OK response");
1394: }
1395: //The Transaction should now be TERMINATED
1396: assertEquals(
1397: "The Transaction did not move to the TERMINATED state "
1398: + "after transmitting an OK response",
1399: TransactionState.TERMINATED, tran.getState());
1400: //Check whether the OK is received by the RI.
1401: waitForMessage();
1402: responseEvent = responseCollector
1403: .extractCollectedResponseEvent();
1404: assertNotNull("The OK response was not received by the RI",
1405: responseEvent);
1406: assertTrue(
1407: "A response different from OK was sent by the TI",
1408: Response.OK == responseEvent.getResponse()
1409: .getStatusCode());
1410:
1411: // Send an ACK to the other side.
1412:
1413: try {
1414: Dialog dialog = responseEvent.getDialog();
1415: Request ack = dialog.createAck(((CSeqHeader) ok
1416: .getHeader(CSeqHeader.NAME)).getSeqNumber());
1417: dialog.sendAck(ack);
1418: } catch (SipException ex) {
1419:
1420: fail("error sending ack ", ex);
1421: }
1422: } catch (Throwable exc) {
1423: exc.printStackTrace();
1424: fail(exc.getClass().getName() + ": " + exc.getMessage());
1425: }
1426: assertTrue(new Exception().getStackTrace()[0].toString(), true);
1427: }
1428:
1429: //==================== end of tests
1430:
1431: //====== STATIC JUNIT ==========
1432: public static Test suite() {
1433: return new TestSuite(
1434: InviteServerTransactionsStateMachineTest.class);
1435: }
1436:
1437: }
|