Esempio n. 1
0
  /** This is a listener method. */
  public void processResponse(ResponseEvent responseEvent) {
    try {

      Response response = responseEvent.getResponse();
      SipProvider sipProvider = (SipProvider) responseEvent.getSource();
      ClientTransaction clientTransaction = responseEvent.getClientTransaction();

      ProxyDebug.println(
          "\n***************************************************************"
              + "\n***************************************************************"
              + "\nResponse "
              + response.getStatusCode()
              + " "
              + response.getReasonPhrase()
              + " received:\n"
              + response.toString());
      ProxyDebug.println("Processing Response in progress");

      if (ProxyDebug.debug) ProxyUtilities.printTransaction(clientTransaction);

      // Henrik - added handling of responses addressed to server
      // If we use a presenceserver, and if statuscode was OK...
      CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);

      if (cseqHeader.getMethod().equals("SUBSCRIBE")) {
        presenceServer.processSubscribeResponse((Response) response.clone(), clientTransaction);
      } else if (cseqHeader.getMethod().equals("NOTIFY")) {
        // presenceServer.processNotifyResponse((Response)response.clone(),
        // clientTransaction);
      }

      responseForwarding.forwardResponse(sipProvider, response, clientTransaction);

    } catch (Exception ex) {
      if (ProxyDebug.debug) {
        ProxyDebug.println("Proxy, processResponse(), internal error, " + "exception raised:");
        ProxyDebug.logException(ex);
      }
    }
  }
  /**
   * Tries to steer a TI client transaction through the following scenario Calling-->Terminated.
   * Apart from state transitions, we also test, retransmissions and proper hiding/passing of
   * messages to the TU.
   */
  public void testCallingTerminatedScenario() {
    try {
      Request invite = createTiInviteRequest(null, null, null);
      ClientTransaction tran = null;
      try {
        eventCollector.collectRequestEvent(riSipProvider);
        tran = tiSipProvider.getNewClientTransaction(invite);
        tran.sendRequest();
      } catch (SipException ex) {
        throw new TiUnexpectedError("A SipExceptionOccurred while trying to send request!", ex);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      waitForMessage();
      RequestEvent inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      if (inviteReceivedEvent == null || inviteReceivedEvent.getRequest() == null)
        throw new TiUnexpectedError("The invite request was not received by the RI!");
      // At this point the ClientTransaction should be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Check Request retransmission
      try {
        eventCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      // Wait for the retransmission timer to fire if it had not already
      // done so.
      if (tran.getRetransmitTimer() > MESSAGES_ARRIVE_FOR)
        sleep((long) tran.getRetransmitTimer() - MESSAGES_ARRIVE_FOR); // subtract
      // the
      // time
      // we
      // waited
      // for
      // the
      // invite
      // Wait for the retransmitted request to arrive
      waitForMessage();
      inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent);
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent.getRequest());
      assertEquals(Request.INVITE, inviteReceivedEvent.getRequest().getMethod());
      // At this point the ClientTransaction should STILL be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Send a 200 OK (final) response from the RI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // The OK response shouldn't trigger any ACKs so let's register
      // a listener with the RI to verify whether that is the case
      SipEventCollector ackCollector = new SipEventCollector();
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      Response ok = null;
      try {
        ok = riMessageFactory.createResponse(Response.OK, inviteReceivedEvent.getRequest());
        addStatus(inviteReceivedEvent.getRequest(), ok);

        // JvB: MUST add Contact too!
        ContactHeader contact =
            riHeaderFactory.createContactHeader(((ToHeader) ok.getHeader("To")).getAddress());
        ok.addHeader(contact);
        // end JvB

        riSipProvider.sendResponse(ok);
      } catch (Throwable ex) {
        throw new TckInternalError("The TCK could not send an OK response back to the TI", ex);
      }
      waitForMessage();
      // Analyze the OK response and Tran state back at the TI
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull(
          "The Tested Implementation did not pass a 200 OK response to the TU!", responseEvent);
      assertNotNull(
          "The Tested Implementation did not pass a 200 OK response to the TU!",
          responseEvent.getResponse());
      assertSame(
          "The OK response was not associated with the right transaction",
          tran,
          responseEvent.getClientTransaction());
      assertSame(
          "A response different from OK was passed to the TU",
          tran,
          responseEvent.getClientTransaction());
      assertEquals(
          "The ClientTransaction did not pass in the TERMINATED state after "
              + "receiving 200 final response",
          tran.getState(),
          TransactionState.TERMINATED);
      // check whether the ackCollector has caught any fish
      RequestEvent ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNull("The TI sent an ACK to an OK (this is TU's job)!", ackReceivedEvent);
      // Now let's retransmit the final response and see that it is
      // passed to the TU (again no ACKs should be sent by the TI)
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // go fish the ack
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      try {
        riSipProvider.sendResponse((Response) ok.clone());
      } catch (Throwable ex) {
        throw new TckInternalError("The TCK could not send an OK response back to the TI", ex);
      }
      waitForMessage();
      // Did we get the 2nd OK?
      responseEvent = eventCollector.extractCollectedResponseEvent();
      /*
       * JvB: see previous comment
       *
       * assertNotNull( "The TI did not pass to the TU a retransmitted OK
       * response!", responseEvent); assertNotNull( "The TI did not pass
       * to the TU a retransmitted OK response!",
       * responseEvent.getResponse()); assertTrue( "The TI passed to the
       * TU a bad response!",
       * responseEvent.getResponse().getStatusCode()==Response.OK);
       */
      // JvB: TBD
      // assertNull( "The TI should filter the retransmitted OK response",
      // responseEvent );

      // We must still be in the terminated state.
      assertEquals(
          "The ClientTransaction mysteriously left the TERMINATED state!",
          tran.getState(),
          TransactionState.TERMINATED);
      // check whether the ackCollector has caught any fish
      ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNull(
          "The TI sent an ACK request to the second OK response "
              + "(OK acks are TU's responsibility)!",
          ackReceivedEvent);
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
  /**
   * Tries to steer a TI client transaction through the following scenario
   * Calling-->Completed-->Terminated. Apart from state transitions, we also test, retransmissions
   * and proper hiding/passing of messages to the TU.
   */
  public void testCallingCompletedTerminatedScenario() {
    try {
      Request invite = createTiInviteRequest(null, null, null);

      // JvB: test
      // ((MessageExt) invite).getFirstViaHeader().setParameter( "rport",
      // null );

      ClientTransaction tran = null;
      try {
        eventCollector.collectRequestEvent(riSipProvider);
        tran = tiSipProvider.getNewClientTransaction(invite);
        tran.sendRequest();
      } catch (SipException ex) {
        throw new TiUnexpectedError("A SipExceptionOccurred while trying to send request!", ex);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      waitForMessage();
      RequestEvent inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      if (inviteReceivedEvent == null || inviteReceivedEvent.getRequest() == null)
        throw new TiUnexpectedError("The invite request was not received by the RI!");
      // At this point the ClientTransaction should be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Check Request retransmission
      try {
        eventCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      // Wait for the retransmission timer to fire if it had not already
      // done so.
      if (tran.getRetransmitTimer() > MESSAGES_ARRIVE_FOR)
        sleep((long) tran.getRetransmitTimer() - MESSAGES_ARRIVE_FOR); // subtract
      // the
      // time
      // we
      // waited
      // for
      // the
      // invite
      // Wait for the retransmitted request to arrive
      waitForMessage();
      inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent);
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent.getRequest());
      assertEquals(Request.INVITE, inviteReceivedEvent.getRequest().getMethod());
      // At this point the ClientTransaction should STILL be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Send a 486 BUSY HERE (final) response from the RI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // The BUSY_HERE response should trigger some ACKs so let's register
      // a listener with the RI
      SipEventCollector ackCollector = new SipEventCollector();
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      Response busyHere = null;
      try {
        busyHere =
            riMessageFactory.createResponse(Response.BUSY_HERE, inviteReceivedEvent.getRequest());
        addStatus(inviteReceivedEvent.getRequest(), busyHere);

        // JvB: set to-tag, check it against the ACK generated
        ((ToHeader) busyHere.getHeader("to")).setTag("ack-to-test");

        riSipProvider.sendResponse((Response) busyHere.clone());
      } catch (Throwable ex) {
        throw new TckInternalError(
            "The TCK could not send a BUSY HERE response back to the TI", ex);
      }
      waitForMessage();
      // Analyze the BUSY_HERE response and Tran state back at the TI
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull(
          "The Tested Implementation did not pass a 300-699 response to the TU!", responseEvent);
      assertNotNull(
          "The Tested Implementation did not pass a 300-699 response to the TU!",
          responseEvent.getResponse());
      assertSame(
          "The BUSY_HERE response was not associated with the right transaction",
          tran,
          responseEvent.getClientTransaction());
      assertSame(
          "A response different from BUSY_HERE was passed to the TU",
          tran,
          responseEvent.getClientTransaction());
      assertEquals(
          "The ClientTransaction did not pass in the COMPLETED state after "
              + "receiving 300-699 final response",
          tran.getState(),
          TransactionState.COMPLETED);
      // check whether the ackCollector has caught any fish
      RequestEvent ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNotNull("The TI did not send an ACK request", ackReceivedEvent);
      assertNotNull("The TI did not send an ACK request", ackReceivedEvent.getRequest());
      assertEquals(Request.ACK, ackReceivedEvent.getRequest().getMethod());
      // Try to kill remaining ACK retransmissions
      // TODO this may not always work .. should give it a specific
      // timeout value
      waitForMessage();
      // Now let's retransmit the final response. This time it shouldn't
      // be
      // passed to the TU but an ACK should still be sent
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // go fish the ack
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      try {
        riSipProvider.sendResponse((Response) busyHere.clone());
      } catch (Throwable ex) {
        throw new TckInternalError(
            "The TCK could not send a BUSY HERE response back to the TI", ex);
      }
      waitForMessage();
      // The TU shouldn't see the retransmitted BUSY_HERE response
      responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNull(
          "The Tested Implementation passed a retransmitted 300-699 response "
              + "to the TU instead of just silently acknowledging it!",
          responseEvent);
      // We must still be in the completed state.
      assertEquals(
          "The ClientTransaction did not stay long enough in the COMPLETED " + "state.",
          tran.getState(),
          TransactionState.COMPLETED);
      // check whether the ackCollector has caught any fish
      ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNotNull("The TI did not send an ACK request to the second response", ackReceivedEvent);
      assertNotNull(
          "The TI did not send an ACK request to the second response",
          ackReceivedEvent.getRequest());

      assertEquals(Request.ACK, ackReceivedEvent.getRequest().getMethod());

      // JvB: verify to tag
      assertEquals(
          "The To header field in the ACK MUST equal the To header field "
              + " in the response being acknowledged",
          "ack-to-test",
          ((ToHeader) ackReceivedEvent.getRequest().getHeader("to")).getTag());
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);

    // Unfortunately we can't assert the TERMINATED state as timerD
    // is not exported by JAIN SIP

  }