} 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 TRYING response
try {
eventCollector.collectResponseEvent(tiSipProvider);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with TI", ex);
}
try {
Response resp = riMessageFactory.createResponse(
Response.TRYING, inviteReceivedEvent.getRequest());
addStatus(inviteReceivedEvent.getRequest(), resp);
riSipProvider.sendResponse(resp);
} catch (Throwable ex) {
throw new TckInternalError(
"The TCK could not send a trying response back to the TI",
ex);
}
waitForMessage();
// Analyze the TRYING response and Tran state back at the TI
ResponseEvent responseEvent = eventCollector
.extractCollectedResponseEvent();
assertNotNull(
"The Tested Implementation did not pass a 1xx response to the TU!",
responseEvent);
assertNotNull(
"The Tested Implementation did not pass a 1xx response to the TU!",
responseEvent.getResponse());
assertTrue(
"A response different from TYING was passed to the TU!",
responseEvent.getResponse().getStatusCode() == Response.TRYING);
assertSame(
"The TRYING response was not associated with the right transaction.",
tran, responseEvent.getClientTransaction());
// verify the the tran state is now PROCEEDING
assertEquals(
"The ClientTransaction did not pass in the PROCEEDING state after "
+ "receiving 1xx provisional response", tran
.getState(), TransactionState.PROCEEDING);
// 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 too, mandatory and tests that ACK is properly
// formatted
((ToHeader) busyHere.getHeader("to")).setTag("busy-here");
riSipProvider.sendResponse(busyHere);
} 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 = 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());
assertEquals(
"A response different from BUSY_HERE was passed to the TU",
Response.BUSY_HERE, responseEvent.getResponse()
.getStatusCode());
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();
// JvB: With auto-dialog-support enabled, the ACK should be filtered
// by the RI
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