/** 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 }