package test.tck.msgflow.callflows.redirect; import javax.sip.*; import javax.sip.address.*; import javax.sip.header.*; import javax.sip.message.*; import org.apache.log4j.Logger; import test.tck.TestHarness; import test.tck.msgflow.callflows.ProtocolObjects; import java.util.*; import junit.framework.TestCase; /** * This class is a UAC template. Shootist is the guy that shoots and shootme is * the guy that gets shot. * * @author M. Ranganathan */ public class Shootist extends TestHarness implements SipListener { private SipProvider sipProvider; private ProtocolObjects protocolObjects; private ContactHeader contactHeader; private ListeningPoint listeningPoint; private ClientTransaction inviteTid; private Dialog dialog; public static final int myPort = 5080; private int peerPort; private String peerHostPort; private int dialogTerminatedCount; private int transctionTerminatedCount; private int transactionCount; private int dialogCount; private boolean byeReceived; private boolean redirectReceived; private SipURI requestURI; private static Logger logger = Logger.getLogger(Shootist.class); public void processRequest(RequestEvent requestReceivedEvent) { Request request = requestReceivedEvent.getRequest(); ServerTransaction serverTransactionId = requestReceivedEvent .getServerTransaction(); logger.info("\n\nRequest " + request.getMethod() + " received at " + protocolObjects.sipStack.getStackName() + " with server transaction id " + serverTransactionId); // We are the UAC so the only request we get is the BYE. if (request.getMethod().equals(Request.BYE)) processBye(request, serverTransactionId); } public void processBye(Request request, ServerTransaction serverTransactionId) { try { logger.info("shootist: got a bye . ServerTxId = " + serverTransactionId); this.byeReceived = true; if (serverTransactionId == null) { logger.info("shootist: null TID."); return; } Dialog dialog = serverTransactionId.getDialog(); assertTrue(dialog == this.dialog); logger.info("Dialog State = " + dialog.getState()); Response response = protocolObjects.messageFactory.createResponse( 200, request); serverTransactionId.sendResponse(response); this.transactionCount++; logger.info("shootist: Sending OK."); logger.info("Dialog State = " + dialog.getState()); ViaHeader via = (ViaHeader) request.getHeader(ViaHeader.NAME); if (via.getTransport().equalsIgnoreCase("UDP")) { assertEquals("Check for Transaction State of Completed", TransactionState.COMPLETED,serverTransactionId.getState()); } else { assertEquals("Check for Transaction State of Completed", TransactionState.TERMINATED,serverTransactionId.getState()); } assertEquals("Check for Dialog state of terminated",DialogState.TERMINATED, dialog.getState() ); } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } } public void processResponse(ResponseEvent responseReceivedEvent) { logger.info("Got a response"); Response response = (Response) responseReceivedEvent.getResponse(); ClientTransaction tid = responseReceivedEvent.getClientTransaction(); CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); logger.info("Response received : Status Code = " + response.getStatusCode() + " " + cseq); if (tid == null) { logger.info("Stray response -- dropping "); return; } logger.info("transaction state is " + tid.getState()); logger.info("Dialog = " + tid.getDialog()); logger.info("Dialog State is " + tid.getDialog().getState()); try { if (response.getStatusCode() == Response.OK) { logger.info("response = " + response); if (cseq.getMethod().equals(Request.INVITE)) { Request ackRequest = dialog.createAck(cseq.getSeqNumber()); logger.info("Sending ACK"); dialog.sendAck(ackRequest); } } else if (response.getStatusCode() == Response.MOVED_TEMPORARILY) { // Dialog dies as soon as you get an error response. assertTrue(tid.getDialog().getState() == DialogState.TERMINATED); assertSame("Dialog Identity should be preserved", tid.getDialog(),this.dialog); this.redirectReceived = true; if (cseq.getMethod().equals(Request.INVITE)) { // lookup the contact header ContactHeader contHdr = (ContactHeader) response .getHeader(ContactHeader.NAME); // we can re-use the from header FromHeader from = ((FromHeader) response .getHeader(FromHeader.NAME)); // we use the to-address, but without the tag ToHeader to = (ToHeader) (response.getHeader(ToHeader.NAME)).clone(); to.removeParameter("tag"); // the call-id can be re-used CallIdHeader callID = ((CallIdHeader) response .getHeader(CallIdHeader.NAME)); // we take the next cseq long seqNo = (((CSeqHeader) response .getHeader(CSeqHeader.NAME)).getSeqNumber()); logger.info("seqNo = " + seqNo); CSeqHeader cseqNew = protocolObjects.headerFactory .createCSeqHeader(++seqNo, "INVITE"); // Create ViaHeaders (either use tcp or udp) ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = protocolObjects.headerFactory .createViaHeader("127.0.0.1", sipProvider .getListeningPoint(protocolObjects.transport).getPort(), protocolObjects.transport, null); // add via headers viaHeaders.add(viaHeader); // create max forwards MaxForwardsHeader maxForwardsHeader = protocolObjects.headerFactory .createMaxForwardsHeader(10); // create invite Request SipURI newUri = (SipURI)this.requestURI.clone(); newUri.setParameter("redirection", "true"); Request invRequest = protocolObjects.messageFactory .createRequest(newUri, "INVITE", callID, cseqNew, from, to, viaHeaders, maxForwardsHeader); // we set the Request URI to the address given SipURI contactURI = protocolObjects.addressFactory.createSipURI(null, this.listeningPoint.getIPAddress()); contactURI.setPort(this.listeningPoint.getPort()); contactURI.setTransportParam(protocolObjects.transport); Address address = protocolObjects.addressFactory.createAddress(contactURI); ContactHeader contact = protocolObjects.headerFactory.createContactHeader(address); invRequest.addHeader(contact); // the contacat header in the response contains where to redirect // the request to -- which in this case happens to be back to the // same location. ContactHeader chdr = (ContactHeader)response.getHeader(ContactHeader.NAME); SipURI sipUri = (SipURI)chdr.getAddress().getURI(); sipUri.setLrParam(); RouteHeader routeHeader = protocolObjects.headerFactory.createRouteHeader(chdr.getAddress()); invRequest.addHeader(routeHeader); logger.info("Sending INVITE to " + contHdr.getAddress().getURI().toString()); inviteTid = sipProvider.getNewClientTransaction(invRequest); this.transactionCount++; logger.info("New TID = " + inviteTid); Thread.sleep(500); inviteTid.sendRequest(); // The 100 response could have returned and changed the state of the transaction and hence this test is not valid. // assertEquals("Expected calling state was " + inviteTid.getState(), inviteTid.getState(),TransactionState.CALLING); logger.info("sendReqeust succeeded " + inviteTid); Dialog dialog = inviteTid.getDialog(); assertTrue("Stack must allocate a new dialog", dialog != this.dialog); this.dialogCount ++; this.dialog = dialog; } } /** * end of modified code */ } catch (Exception ex) { ex.printStackTrace(); fail("unexpeced exception"); } } public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { logger.info("Transaction Time out"); fail("Unexpected event"); } public SipProvider createProvider() throws Exception { logger.info("Shootist: createProvider()"); listeningPoint = protocolObjects.sipStack.createListeningPoint( "127.0.0.1", myPort, protocolObjects.transport); this.sipProvider = protocolObjects.sipStack .createSipProvider(listeningPoint); assertTrue("listening point should be the same as what the provider returns for this transport", listeningPoint == sipProvider.getListeningPoint(protocolObjects.transport)); return sipProvider; } public void sendInvite() { try { /** * either use udp or tcp */ String fromName = "BigGuy"; String fromSipAddress = "here.com"; String fromDisplayName = "The Master Blaster"; String toSipAddress = "there.com"; String toUser = "LittleGuy"; String toDisplayName = "The Little Blister"; // create >From Header SipURI fromAddress = protocolObjects.addressFactory.createSipURI( fromName, fromSipAddress); Address fromNameAddress = protocolObjects.addressFactory .createAddress(fromAddress); fromNameAddress.setDisplayName(fromDisplayName); FromHeader fromHeader = protocolObjects.headerFactory .createFromHeader(fromNameAddress, "12345"); // create To Header SipURI toAddress = protocolObjects.addressFactory.createSipURI( toUser, toSipAddress); Address toNameAddress = protocolObjects.addressFactory .createAddress(toAddress); toNameAddress.setDisplayName(toDisplayName); ToHeader toHeader = protocolObjects.headerFactory.createToHeader( toNameAddress, null); // create Request URI this.requestURI = protocolObjects.addressFactory.createSipURI( toUser, peerHostPort); // Create ViaHeaders ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = protocolObjects.headerFactory .createViaHeader("127.0.0.1", sipProvider .getListeningPoint(protocolObjects.transport).getPort(), protocolObjects.transport, null); // add via headers viaHeaders.add(viaHeader); // Create ContentTypeHeader ContentTypeHeader contentTypeHeader = protocolObjects.headerFactory .createContentTypeHeader("application", "sdp"); // Create a new CallId header CallIdHeader callIdHeader = sipProvider.getNewCallId(); // JvB: Make sure that the implementation matches the messagefactory callIdHeader = protocolObjects.headerFactory.createCallIdHeader( callIdHeader.getCallId() ); // Create a new Cseq header CSeqHeader cSeqHeader = protocolObjects.headerFactory .createCSeqHeader(1L, Request.INVITE); // Create a new MaxForwardsHeader MaxForwardsHeader maxForwards = protocolObjects.headerFactory .createMaxForwardsHeader(70); // Create the request. Request request = protocolObjects.messageFactory.createRequest( requestURI, Request.INVITE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); // Create contact headers String host = "127.0.0.1"; SipURI contactUrl = protocolObjects.addressFactory.createSipURI( fromName, host); /** * either use tcp or udp */ contactUrl.setPort(listeningPoint.getPort()); contactUrl.setTransportParam(protocolObjects.transport); // Create the contact name address. Address contactAddress = protocolObjects.addressFactory .createAddress(contactUrl); contactUrl.setLrParam(); // Add the contact address. contactAddress.setDisplayName(fromName); contactHeader = protocolObjects.headerFactory .createContactHeader(contactAddress); request.addHeader(contactHeader); SipURI uri = protocolObjects.addressFactory.createSipURI(null, "127.0.0.1"); uri.setLrParam(); uri.setTransportParam(protocolObjects.transport); uri.setPort(this.peerPort); Address address = protocolObjects.addressFactory.createAddress(uri); RouteHeader routeHeader = protocolObjects.headerFactory.createRouteHeader(address); request.addHeader(routeHeader); Header callInfoHeader = protocolObjects.headerFactory.createHeader( "Call-Info", "<http://www.antd.nist.gov>"); request.addHeader(callInfoHeader); // Create the client transaction. inviteTid = sipProvider.getNewClientTransaction(request); this.transactionCount ++; //assertTrue(inviteTid.getState() == TransactionState.CALLING); logger.info("client tx = " + inviteTid); this.dialog = inviteTid.getDialog(); this.dialogCount++; assertTrue(this.dialog != null); //assertTrue(dialog.getState() == null); // send the request out. inviteTid.sendRequest(); } catch (Exception ex) { logger.error(ex.getMessage(),ex); fail("unexpected exception"); } } public Shootist (ProtocolObjects protocolObjects) { this.protocolObjects = protocolObjects; this.peerPort = Shootme.myPort; this.peerHostPort = "127.0.0.1:"+ peerPort; } public void processIOException(IOExceptionEvent exceptionEvent) { logger.info("IOException happened for " + exceptionEvent.getHost() + " port = " + exceptionEvent.getPort()); } public void processTransactionTerminated( TransactionTerminatedEvent transactionTerminatedEvent) { logger.info("Transaction terminated event recieved for " + transactionTerminatedEvent.getClientTransaction()); this.transctionTerminatedCount++; } public void processDialogTerminated( DialogTerminatedEvent dialogTerminatedEvent) { this.dialogTerminatedCount++; } public void checkState() { //assertTrue(dialogTerminatedCount == dialogCount); logger.info("byeRecieved = " + this.byeReceived); logger.info("redirectRecieved" + this.redirectReceived); assertTrue(this.byeReceived && this.redirectReceived ); } }