@Test // For github issue #600, At the DB the IncomingPhoneNumber is '+2222' and we dial '2222',
        // Restcomm should find this number even without the '+'
  public synchronized void testDialClientAliceWithoutPlusSign()
      throws InterruptedException, ParseException {
    stubFor(
        get(urlPathEqualTo("/1111"))
            .willReturn(
                aResponse()
                    .withStatus(200)
                    .withHeader("Content-Type", "text/xml")
                    .withBody(dialClientRcml)));

    // Phone2 register as alice
    SipURI uri = aliceSipStack.getAddressFactory().createSipURI(null, "127.0.0.1:5080");
    assertTrue(alicePhone.register(uri, "alice", "1234", aliceContact, 3600, 3600));

    // Prepare second phone to receive call
    SipCall aliceCall = alicePhone.createSipCall();
    aliceCall.listenForIncomingCall();

    // Create outgoing call with first phone
    final SipCall bobCall = bobPhone.createSipCall();
    bobCall.initiateOutgoingCall(
        bobContact, "sip:[email protected]:5080", null, body, "application", "sdp", null, null);
    assertLastOperationSuccess(bobCall);
    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
    final int response = bobCall.getLastReceivedResponse().getStatusCode();
    assertTrue(response == Response.TRYING || response == Response.RINGING);

    if (response == Response.TRYING) {
      assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
      assertEquals(Response.RINGING, bobCall.getLastReceivedResponse().getStatusCode());
    }

    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
    assertEquals(Response.OK, bobCall.getLastReceivedResponse().getStatusCode());

    bobCall.sendInviteOkAck();
    assertTrue(!(bobCall.getLastReceivedResponse().getStatusCode() >= 400));

    assertTrue(aliceCall.waitForIncomingCall(30 * 1000));
    assertTrue(aliceCall.sendIncomingCallResponse(Response.RINGING, "Ringing-Alice", 3600));
    String receivedBody = new String(aliceCall.getLastReceivedRequest().getRawContent());
    assertTrue(
        aliceCall.sendIncomingCallResponse(
            Response.OK, "OK-Alice", 3600, receivedBody, "application", "sdp", null, null));
    assertTrue(aliceCall.waitForAck(50 * 1000));

    Thread.sleep(3000);

    // hangup.
    bobCall.disconnect();

    aliceCall.listenForDisconnect();
    assertTrue(aliceCall.waitForDisconnect(30 * 1000));
    assertTrue(aliceCall.respondToDisconnect());
  }
  @Test
  // Non regression test for
  // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out
  // with URL screening
  public synchronized void testDialSipTagScreening() throws InterruptedException, ParseException {
    stubFor(
        get(urlPathEqualTo("/1111"))
            .willReturn(
                aResponse()
                    .withStatus(200)
                    .withHeader("Content-Type", "text/xml")
                    .withBody(dialSipTagScreeningRcml)));

    stubFor(
        get(urlPathEqualTo("/screening"))
            .willReturn(
                aResponse()
                    .withStatus(200)
                    .withHeader("Content-Type", "text/xml")
                    .withBody(screeningRcml)));

    // Phone2 register as alice
    SipURI uri = aliceSipStack.getAddressFactory().createSipURI(null, "127.0.0.1:5080");
    assertTrue(alicePhone.register(uri, "alice", "1234", aliceContact, 3600, 3600));

    // Prepare second phone to receive call
    SipCall aliceCall = alicePhone.createSipCall();
    aliceCall.listenForIncomingCall();

    // Create outgoing call with first phone
    final SipCall bobCall = bobPhone.createSipCall();
    bobCall.initiateOutgoingCall(
        bobContact, dialRestcomm, null, body, "application", "sdp", null, null);
    assertLastOperationSuccess(bobCall);
    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
    final int response = bobCall.getLastReceivedResponse().getStatusCode();
    assertTrue(response == Response.TRYING || response == Response.RINGING);

    if (response == Response.TRYING) {
      assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
      assertEquals(Response.RINGING, bobCall.getLastReceivedResponse().getStatusCode());
    }

    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
    assertEquals(Response.OK, bobCall.getLastReceivedResponse().getStatusCode());

    bobCall.sendInviteOkAck();
    assertTrue(!(bobCall.getLastReceivedResponse().getStatusCode() >= 400));

    assertTrue(aliceCall.waitForIncomingCall(30 * 1000));
    MessageExt invite = (MessageExt) aliceCall.getLastReceivedRequest().getMessage();
    assertNotNull(invite);
    assertEquals(Request.INVITE, invite.getCSeqHeader().getMethod());
    Header mycustomheader = invite.getHeader("X-mycustomheader");
    Header myotherheader = invite.getHeader("X-myotherheader");
    assertNotNull(mycustomheader);
    assertNotNull(myotherheader);

    assertTrue(aliceCall.sendIncomingCallResponse(Response.RINGING, "Ringing-Alice", 3600));
    String receivedBody = new String(aliceCall.getLastReceivedRequest().getRawContent());
    ArrayList<String> headers = new ArrayList<String>();
    Header customHeader =
        aliceSipStack.getHeaderFactory().createHeader("X-mycustomheader", "customValue");
    Header otherHeader =
        aliceSipStack.getHeaderFactory().createHeader("X-myothereader", "customOtherValue");
    headers.add(customHeader.toString());
    headers.add(otherHeader.toString());
    assertTrue(
        aliceCall.sendIncomingCallResponse(
            Response.OK, "OK-Alice", 3600, receivedBody, "application", "sdp", headers, null));
    assertTrue(aliceCall.waitForAck(50 * 1000));

    Thread.sleep(3000);

    // hangup.
    bobCall.disconnect();

    aliceCall.disconnect();
    assertTrue(aliceCall.waitForDisconnect(30 * 1000));
  }
  // Non regression test for https://github.com/Mobicents/RestComm/issues/612
  @Test
  public synchronized void testRecord_ExecuteRCML_ReturnedFromActionURL()
      throws InterruptedException, ParseException {

    stubFor(
        get(urlPathEqualTo("/1111"))
            .willReturn(
                aResponse()
                    .withStatus(200)
                    .withHeader("Content-Type", "text/xml")
                    .withBody(recordWithActionRcml)));

    stubFor(
        get(urlPathEqualTo("/recordAction"))
            .willReturn(
                aResponse()
                    .withStatus(200)
                    .withHeader("Content-Type", "text/xml")
                    .withBody(actionUrlRcml)));

    // Prepare Fotini phone to receive a call
    final SipCall aliceCall = alicePhone.createSipCall();
    aliceCall.listenForIncomingCall();

    // Initiate a call using Bob
    final SipCall bobCall = bobPhone.createSipCall();

    bobCall.initiateOutgoingCall(
        bobContact, dialRestcomm, null, body, "application", "sdp", null, null);
    assertLastOperationSuccess(bobCall);

    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));

    final int response = bobCall.getLastReceivedResponse().getStatusCode();
    assertTrue(response == Response.TRYING || response == Response.RINGING);
    if (response == Response.TRYING) {
      assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
      assertEquals(Response.RINGING, bobCall.getLastReceivedResponse().getStatusCode());
    }

    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
    assertEquals(Response.OK, bobCall.getLastReceivedResponse().getStatusCode());
    bobCall.sendInviteOkAck();
    assertTrue(!(bobCall.getLastReceivedResponse().getStatusCode() >= 400));

    // At this point bob leaves a voicemail

    // Now Fotini should receive a call
    assertTrue(aliceCall.waitForIncomingCall(30 * 1000));
    assertTrue(aliceCall.sendIncomingCallResponse(100, "Trying-Fotini", 600));
    assertTrue(aliceCall.sendIncomingCallResponse(180, "Ringing-Fotini", 600));
    String receivedBody = new String(aliceCall.getLastReceivedRequest().getRawContent());
    assertTrue(
        aliceCall.sendIncomingCallResponse(
            Response.OK, "OK-Fotini", 3600, receivedBody, "application", "sdp", null, null));
    assertTrue(aliceCall.waitForAck(5000));
    aliceCall.listenForDisconnect();

    Thread.sleep(2000);

    // hangup.

    assertTrue(bobCall.disconnect());

    assertTrue(aliceCall.waitForDisconnect(50 * 1000));
    assertTrue(aliceCall.respondToDisconnect());
  }
  //    @Ignore
  @Test
  // Non regression test for
  // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out
  // in auth manner
  public synchronized void testDialSipAuth() throws InterruptedException, ParseException {
    stubFor(
        get(urlPathEqualTo("/1111"))
            .willReturn(
                aResponse()
                    .withStatus(200)
                    .withHeader("Content-Type", "text/xml")
                    .withBody(dialSipAuthRcml)));

    // Phone2 register as alice
    SipURI uri = aliceSipStack.getAddressFactory().createSipURI(null, "127.0.0.1:5080");
    assertTrue(alicePhone.register(uri, "alice", "1234", aliceContact, 3600, 3600));

    // Prepare second phone to receive call
    SipCall aliceCall = alicePhone.createSipCall();
    aliceCall.listenForIncomingCall();

    // Create outgoing call with first phone
    final SipCall bobCall = bobPhone.createSipCall();
    bobCall.initiateOutgoingCall(
        bobContact, dialRestcomm, null, body, "application", "sdp", null, null);
    assertLastOperationSuccess(bobCall);
    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
    final int response = bobCall.getLastReceivedResponse().getStatusCode();
    assertTrue(response == Response.TRYING || response == Response.RINGING);

    if (response == Response.TRYING) {
      assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
      assertEquals(Response.RINGING, bobCall.getLastReceivedResponse().getStatusCode());
    }

    assertTrue(bobCall.waitOutgoingCallResponse(5 * 1000));
    assertEquals(Response.OK, bobCall.getLastReceivedResponse().getStatusCode());

    bobCall.sendInviteOkAck();
    assertTrue(!(bobCall.getLastReceivedResponse().getStatusCode() >= 400));

    assertTrue(aliceCall.waitForIncomingCall(30 * 1000));
    MessageExt invite = (MessageExt) aliceCall.getLastReceivedRequest().getMessage();
    assertNotNull(invite);
    assertEquals(Request.INVITE, invite.getCSeqHeader().getMethod());
    Header mycustomheader = invite.getHeader("X-mycustomheader");
    Header myotherheader = invite.getHeader("X-myotherheader");
    assertNotNull(mycustomheader);
    assertNotNull(myotherheader);

    DigestServerAuthenticationMethod dsam = new DigestServerAuthenticationMethod();
    dsam.initialize(); // it should read values from file, now all static

    ProxyAuthenticateHeader proxyAuthenticate =
        aliceSipStack.getHeaderFactory().createProxyAuthenticateHeader(dsam.getScheme());
    proxyAuthenticate.setParameter("realm", dsam.getRealm(null));
    proxyAuthenticate.setParameter("nonce", dsam.generateNonce());
    // proxyAuthenticateImpl.setParameter("domain",authenticationMethod.getDomain());
    proxyAuthenticate.setParameter("opaque", "");

    proxyAuthenticate.setParameter("algorithm", dsam.getAlgorithm());
    ArrayList<Header> headers = new ArrayList<Header>();
    headers.add(proxyAuthenticate);
    assertTrue(
        aliceCall.sendIncomingCallResponse(
            Response.PROXY_AUTHENTICATION_REQUIRED, "Non authorized", 3600, headers, null, null));

    assertTrue(aliceCall.waitForIncomingCall(30 * 1000));
    invite = (MessageExt) aliceCall.getLastReceivedRequest().getMessage();
    assertNotNull(invite.getHeader(ProxyAuthorizationHeader.NAME));

    ProxyAuthorizationHeader proxyAuthorization =
        (ProxyAuthorizationHeader) invite.getHeader(ProxyAuthorizationHeader.NAME);

    boolean res = dsam.doAuthenticate("alice", "1234", proxyAuthorization, (Request) invite);
    assertTrue(res);

    assertTrue(aliceCall.sendIncomingCallResponse(Response.RINGING, "Ringing-Alice", 3600));
    String receivedBody = new String(aliceCall.getLastReceivedRequest().getRawContent());
    assertTrue(
        aliceCall.sendIncomingCallResponse(
            Response.OK, "OK-Alice", 3600, receivedBody, "application", "sdp", null, null));
    assertTrue(aliceCall.waitForAck(50 * 1000));
    aliceCall.listenForDisconnect();

    Thread.sleep(3000);

    // hangup.
    bobCall.disconnect();

    assertTrue(aliceCall.waitForDisconnect(30 * 1000));
  }
  @Test
  public void testBothSides() throws Exception {
    assertTrue(ua.register("amit", "a1b2c3d4", null, 600, 5000));

    SipPhone ub =
        sipStack2.createSipPhone(PROXY_HOST, PROXY_PROTO, PROXY_PORT, "sip:[email protected]");
    assertTrue(ub.register("becky", "a1b2c3d4", null, 600, 5000));

    SipCall callA = ua.createSipCall();
    SipCall callB = ub.createSipCall();

    callB.listenForIncomingCall();
    Thread.sleep(100);

    callA.initiateOutgoingCall("sip:[email protected]", null); // "127.0.0.1:4000/UDP"
    assertLastOperationSuccess("a initiate call - " + callA.format(), callA);

    callB.waitForIncomingCall(3000);
    assertLastOperationSuccess("b wait incoming call - " + callB.format(), callB);

    callB.sendIncomingCallResponse(Response.RINGING, null, -1);
    assertLastOperationSuccess("b send RINGING - " + callB.format(), callB);

    Thread.sleep(1000);

    callB.sendIncomingCallResponse(Response.OK, "Answer - Hello world", 0);
    assertLastOperationSuccess("b send OK - " + callB.format(), callB);

    callA.waitOutgoingCallResponse(10000);
    assertLastOperationSuccess("a wait 1st response - " + callA.format(), callA);
    assertTrue(
        "Unexpected 1st response received",
        (callA.getReturnCode() == Response.RINGING || callA.getReturnCode() == Response.TRYING));
    if (callA.getLastReceivedResponse().getStatusCode() == Response.RINGING) {
      assertNotNull(
          "Default response reason not sent", callA.getLastReceivedResponse().getReasonPhrase());
      assertEquals(
          "Unexpected default reason",
          "Ringing",
          callA.getLastReceivedResponse().getReasonPhrase());
    }

    callA.waitOutgoingCallResponse(5000);
    assertLastOperationSuccess("a wait 2nd response - " + callA.format(), callA);
    callA.waitOutgoingCallResponse(2000);

    assertEquals(
        "Unexpected final response received",
        Response.OK,
        callA.getLastReceivedResponse().getStatusCode());

    callA.sendInviteOkAck();
    assertLastOperationSuccess("Failure sending ACK - " + callA.format(), callA);

    Thread.sleep(1000);

    callA.listenForDisconnect();
    assertLastOperationSuccess("a listen disc - " + callA.format(), callA);

    callB.disconnect();
    assertLastOperationSuccess("b disc - " + callB.format(), callB);

    callA.waitForDisconnect(5000);
    assertLastOperationSuccess("a wait disc - " + callA.format(), callA);

    callA.respondToDisconnect();
    assertLastOperationSuccess("a respond to disc - " + callA.format(), callA);

    Thread.sleep(1000);
    ub.dispose();
  }