package examples.forked.invite; import gov.nist.javax.sip.address.SipUri; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Properties; import javax.sip.ClientTransaction; import javax.sip.DialogTerminatedEvent; import javax.sip.IOExceptionEvent; import javax.sip.ListeningPoint; import javax.sip.RequestEvent; import javax.sip.ResponseEvent; import javax.sip.ServerTransaction; import javax.sip.SipFactory; import javax.sip.SipListener; import javax.sip.SipProvider; import javax.sip.SipStack; import javax.sip.TimeoutEvent; import javax.sip.TransactionTerminatedEvent; import javax.sip.address.Address; import javax.sip.address.AddressFactory; import javax.sip.address.SipURI; import javax.sip.header.CSeqHeader; import javax.sip.header.HeaderFactory; import javax.sip.header.RecordRouteHeader; import javax.sip.header.RouteHeader; import javax.sip.header.ToHeader; import javax.sip.header.ViaHeader; import javax.sip.message.MessageFactory; import javax.sip.message.Request; import javax.sip.message.Response; import junit.framework.TestCase; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.FileAppender; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; /** * A very simple forking proxy server. * * @author M. Ranganathan * */ public class Proxy extends TestCase implements SipListener { //private ServerTransaction st; private SipProvider inviteServerTxProvider; private Hashtable clientTxTable = new Hashtable(); private static String transport = "udp"; private static String host = "127.0.0.1"; private int port = 5070; private SipProvider sipProvider; private static String unexpectedException = "Unexpected exception"; private static Logger logger = Logger.getLogger(Proxy.class); static { try { logger.addAppender(new FileAppender(new SimpleLayout(), ProtocolObjects.logFileDirectory + "proxlog.txt")); } catch (Exception ex) { throw new RuntimeException("could not open shootistconsolelog.txt"); } } public void processRequest(RequestEvent requestEvent) { try { Request request = requestEvent.getRequest(); SipProvider sipProvider = (SipProvider) requestEvent.getSource(); this.inviteServerTxProvider = sipProvider; if (request.getMethod().equals(Request.INVITE)) { ListeningPoint lp = sipProvider.getListeningPoint(transport); String host = lp.getIPAddress(); int port = lp.getPort(); ServerTransaction st = null; if (requestEvent.getServerTransaction() == null) { st = sipProvider.getNewServerTransaction(request); } Request newRequest = (Request) request.clone(); SipURI sipUri = ProtocolObjects.addressFactory.createSipURI("UA1", "127.0.0.1"); sipUri.setPort(5080); sipUri.setLrParam(); Address address = ProtocolObjects.addressFactory.createAddress("client1", sipUri); RouteHeader rheader = ProtocolObjects.headerFactory.createRouteHeader(address); newRequest.addFirst(rheader); ViaHeader viaHeader = ProtocolObjects.headerFactory.createViaHeader(host, port, transport, null); newRequest.addFirst(viaHeader); ClientTransaction ct1 = sipProvider .getNewClientTransaction(newRequest); sipUri = ProtocolObjects.addressFactory.createSipURI("proxy", "127.0.0.1"); address = ProtocolObjects.addressFactory.createAddress("proxy",sipUri); sipUri.setPort(5070); sipUri.setLrParam(); RecordRouteHeader recordRoute = ProtocolObjects.headerFactory.createRecordRouteHeader(address); newRequest.addHeader(recordRoute); ct1.setApplicationData(st); this.clientTxTable.put(new Integer(5080), ct1); newRequest = (Request) request.clone(); sipUri = ProtocolObjects.addressFactory.createSipURI("UA2", "127.0.0.1"); sipUri.setLrParam(); sipUri.setPort(5090); address = ProtocolObjects.addressFactory.createAddress("client2", sipUri); rheader = ProtocolObjects.headerFactory.createRouteHeader(address); newRequest.addFirst(rheader); viaHeader = ProtocolObjects.headerFactory.createViaHeader(host, port, transport, null); newRequest.addFirst(viaHeader); sipUri = ProtocolObjects.addressFactory.createSipURI("proxy", "127.0.0.1"); sipUri.setPort(5070); sipUri.setLrParam(); sipUri.setTransportParam(transport); address = ProtocolObjects.addressFactory.createAddress("proxy",sipUri); recordRoute = ProtocolObjects.headerFactory.createRecordRouteHeader(address); newRequest.addHeader(recordRoute); ClientTransaction ct2 = sipProvider .getNewClientTransaction(newRequest); ct2.setApplicationData(st); this.clientTxTable.put(new Integer(5090), ct2); // Send the requests out to the two listening points of the client. ct2.sendRequest(); ct1.sendRequest(); } else { // Remove the topmost route header // The route header will make sure it gets to the right place. logger.info("proxy: Got a request " + request.getMethod()); Request newRequest = (Request) request.clone(); newRequest.removeFirst(RouteHeader.NAME); sipProvider.sendRequest(newRequest); } } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } } public void processResponse(ResponseEvent responseEvent) { try { Response response = responseEvent.getResponse(); CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); logger.info("ClientTxID = " + responseEvent.getClientTransaction() + " client tx id " + ((ViaHeader) response.getHeader(ViaHeader.NAME)).getBranch() + " CSeq header = " + response.getHeader(CSeqHeader.NAME) + " status code = " + response.getStatusCode()); // JvB: stateful proxy MUST NOT forward 100 Trying if ( response.getStatusCode() == 100 ) return; if (cseq.getMethod().equals(Request.INVITE)) { ClientTransaction ct = responseEvent.getClientTransaction(); if (ct != null) { ServerTransaction st = (ServerTransaction) ct .getApplicationData(); // Strip the topmost via header Response newResponse = (Response) response.clone(); newResponse.removeFirst(ViaHeader.NAME); // The server tx goes to the terminated state. st.sendResponse(newResponse); } else { // Client tx has already terminated but the UA is retransmitting // just forward the response statelessly. // Strip the topmost via header Response newResponse = (Response) response.clone(); newResponse.removeFirst(ViaHeader.NAME); // Send the retransmission statelessly this.inviteServerTxProvider.sendResponse(newResponse); } } else { // Can be BYE due to Record-Route logger.info("Got a non-invite response " + response); SipProvider p = (SipProvider) responseEvent.getSource(); response.removeFirst( ViaHeader.NAME ); p.sendResponse( response ); } } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } } public void processTimeout(TimeoutEvent timeoutEvent) { logger.info("Timeout occured"); } public void processIOException(IOExceptionEvent exceptionEvent) { logger.info("IOException occured"); } public SipProvider createSipProvider() { try { ListeningPoint listeningPoint = ProtocolObjects.sipStack.createListeningPoint( host, port, transport); sipProvider = ProtocolObjects.sipStack .createSipProvider(listeningPoint); return sipProvider; } catch (Exception ex) { logger.error(unexpectedException, ex); fail(unexpectedException); return null; } } public void processTransactionTerminated( TransactionTerminatedEvent transactionTerminatedEvent) { logger.info("Transaction terminated event occured -- cleaning up"); if (!transactionTerminatedEvent.isServerTransaction()) { ClientTransaction ct = transactionTerminatedEvent .getClientTransaction(); for (Iterator it = this.clientTxTable.values().iterator(); it .hasNext();) { if (it.next().equals(ct)) { it.remove(); } } } else { logger.info("Server tx terminated! "); } } public void processDialogTerminated( DialogTerminatedEvent dialogTerminatedEvent) { logger.info("HUH!! why do i see this event??"); } public static void main(String[] args) throws Exception { logger.addAppender(new ConsoleAppender(new SimpleLayout())); ProtocolObjects.init("proxy",false); Proxy proxy = new Proxy(); proxy.createSipProvider(); proxy.sipProvider.addSipListener(proxy); } }