package examples.prack; import javax.sip.*; import javax.sip.address.*; import javax.sip.header.*; import javax.sip.message.*; import java.util.*; /** * 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 Shootme implements SipListener { private static AddressFactory addressFactory; private static MessageFactory messageFactory; private static HeaderFactory headerFactory; private static SipStack sipStack; private static final String myAddress = "127.0.0.1"; private static final int myPort = 5070; protected ServerTransaction inviteTid; private Request inviteRequest; private Dialog dialog; private String toTag; protected static final String usageString = "java " + "examples.shootist.Shootist \n" + ">>>> is your class path set to the root?"; private static void usage() { System.out.println(usageString); System.exit(0); } public void processRequest(RequestEvent requestEvent) { Request request = requestEvent.getRequest(); ServerTransaction serverTransactionId = requestEvent .getServerTransaction(); System.out.println("\n\nRequest " + request.getMethod() + " received at " + sipStack.getStackName() + " with server transaction id " + serverTransactionId); if (request.getMethod().equals(Request.INVITE)) { processInvite(requestEvent, serverTransactionId); } else if (request.getMethod().equals(Request.ACK)) { processAck(requestEvent, serverTransactionId); } else if (request.getMethod().equals(Request.BYE)) { processBye(requestEvent, serverTransactionId); } else if (request.getMethod().equals(Request.CANCEL)) { processCancel(requestEvent, serverTransactionId); } else if (request.getMethod().equals(Request.PRACK)) { processPrack(requestEvent, serverTransactionId); } } private void processPrack(RequestEvent requestEvent, ServerTransaction serverTransactionId) { try { System.out.println("shootme: got an PRACK! "); System.out.println("Dialog State = " + dialog.getState()); /** * JvB: First, send 200 OK for PRACK */ Request prack = requestEvent.getRequest(); Response prackOk = messageFactory.createResponse( 200, prack ); serverTransactionId.sendResponse( prackOk ); /** * Send a 200 OK response to complete the 3 way handshake for the * INIVTE. */ Response response = messageFactory.createResponse(200, inviteRequest); ToHeader to = (ToHeader) response.getHeader(ToHeader.NAME); to.setTag(this.toTag); Address address = addressFactory.createAddress("Shootme <sip:" + myAddress + ":" + myPort + ">"); ContactHeader contactHeader = headerFactory .createContactHeader(address); response.addHeader(contactHeader); inviteTid.sendResponse(response); } catch (Exception ex) { ex.printStackTrace(); } } public void processResponse(ResponseEvent responseEvent) { } /** * Process the ACK request. Send the bye and complete the call flow. */ public void processAck(RequestEvent requestEvent, ServerTransaction serverTransaction) { try { System.out.println("shootme: got an ACK! Sending a BYE"); System.out.println("Dialog State = " + dialog.getState()); Dialog dialog = serverTransaction.getDialog(); SipProvider provider = (SipProvider) requestEvent.getSource(); Request byeRequest = dialog.createRequest(Request.BYE); ClientTransaction ct = provider.getNewClientTransaction(byeRequest); dialog.sendRequest(ct); } catch (Exception ex) { ex.printStackTrace(); } } /** * Process the invite request. */ public void processInvite(RequestEvent requestEvent, ServerTransaction serverTransaction) { SipProvider sipProvider = (SipProvider) requestEvent.getSource(); Request request = requestEvent.getRequest(); try { System.out.println("shootme: got an Invite sending Trying"); // System.out.println("shootme: " + request); Response response = messageFactory.createResponse(Response.TRYING, request); ServerTransaction st = requestEvent.getServerTransaction(); if (st == null) { st = sipProvider.getNewServerTransaction(request); } dialog = st.getDialog(); st.sendResponse(response); // reliable provisional response. Use the API here! // Response okResponse = messageFactory.createResponse(183, request); Response sessionProgress = dialog.createReliableProvisionalResponse( Response.SESSION_PROGRESS ); ToHeader toHeader = (ToHeader) sessionProgress.getHeader(ToHeader.NAME); this.toTag = "4321"; toHeader.setTag(toTag); // Application is supposed to set. this.inviteTid = st; this.inviteRequest = request; System.out.println("sending reliable provisional response."); // It is essential to use this API here! dialog.sendReliableProvisionalResponse(sessionProgress); // new Timer().schedule(new MyTimerTask(this), 100); } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } } /** * Process the bye request. */ public void processBye(RequestEvent requestEvent, ServerTransaction serverTransactionId) { SipProvider sipProvider = (SipProvider) requestEvent.getSource(); Request request = requestEvent.getRequest(); try { System.out.println("shootme: got a bye sending OK."); Response response = messageFactory.createResponse(200, request); serverTransactionId.sendResponse(response); System.out.println("Dialog State is " + serverTransactionId.getDialog().getState()); } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } } public void processCancel(RequestEvent requestEvent, ServerTransaction serverTransactionId) { SipProvider sipProvider = (SipProvider) requestEvent.getSource(); Request request = requestEvent.getRequest(); try { System.out.println("shootme: got a cancel."); if (serverTransactionId == null) { System.out.println("shootme: null tid."); return; } Response response = messageFactory.createResponse(200, request); serverTransactionId.sendResponse(response); if (dialog.getState() != DialogState.CONFIRMED) { response = messageFactory.createResponse( Response.REQUEST_TERMINATED, inviteRequest); inviteTid.sendResponse(response); } } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } } public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { Transaction transaction; if (timeoutEvent.isServerTransaction()) { transaction = timeoutEvent.getServerTransaction(); } else { transaction = timeoutEvent.getClientTransaction(); } System.out.println("state = " + transaction.getState()); System.out.println("dialog = " + transaction.getDialog()); System.out.println("dialogState = " + transaction.getDialog().getState()); System.out.println("Transaction Time out"); } public void init() { SipFactory sipFactory = null; sipStack = null; sipFactory = SipFactory.getInstance(); sipFactory.setPathName("gov.nist"); Properties properties = new Properties(); properties.setProperty("javax.sip.STACK_NAME", "shootme"); // You need 16 for logging traces. 32 for debug + traces. // Your code will limp at 32 but it is best for debugging. properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "shootmedebug.txt"); properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "shootmelog.txt"); try { // Create SipStack object sipStack = sipFactory.createSipStack(properties); System.out.println("sipStack = " + sipStack); } catch (PeerUnavailableException e) { // could not find // gov.nist.jain.protocol.ip.sip.SipStackImpl // in the classpath e.printStackTrace(); System.err.println(e.getMessage()); if (e.getCause() != null) e.getCause().printStackTrace(); System.exit(0); } try { headerFactory = sipFactory.createHeaderFactory(); addressFactory = sipFactory.createAddressFactory(); messageFactory = sipFactory.createMessageFactory(); ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", 5070, "udp"); Shootme listener = this; SipProvider sipProvider = sipStack.createSipProvider(lp); System.out.println("udp provider " + sipProvider); sipProvider.addSipListener(listener); } catch (Exception ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); usage(); } } public static void main(String args[]) { new Shootme().init(); } public void processIOException(IOExceptionEvent exceptionEvent) { System.out.println("IOException"); } public void processTransactionTerminated( TransactionTerminatedEvent transactionTerminatedEvent) { System.out.println("Transaction terminated event recieved"); } public void processDialogTerminated( DialogTerminatedEvent dialogTerminatedEvent) { System.out.println("Dialog terminated event recieved"); } }