All Downloads are FREE. Search and download functionalities are using the official Maven repository.

test.tck.msgflow.callflows.recroute.Proxy Maven / Gradle / Ivy

package test.tck.msgflow.callflows.recroute;

import java.util.Hashtable;

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.SipListener;
import javax.sip.SipProvider;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionState;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.RecordRouteHeader;
import javax.sip.header.RouteHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;

import org.apache.log4j.Logger;

import test.tck.TestHarness;
import test.tck.msgflow.callflows.ProtocolObjects;

/**
 * A very simple Record-Routing proxy server.
 * 
 * @author M. Ranganathan
 * @author Jeroen van Bemmel
 * 
 */
public class Proxy extends TestHarness implements SipListener {

	// private ServerTransaction st;

	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("test.tck");

	private ProtocolObjects protocolObjects;

	private boolean ackSeen;

	private boolean inviteSeen;

	private boolean byeSeen;

	private int infoCount = 0;
	

	public void checkState() {
		TestHarness.assertTrue("INVITE should be seen by proxy", inviteSeen);
		TestHarness.assertTrue("Should see two INFO messages", infoCount == 2);
		TestHarness.assertTrue("BYE should be seen by proxy", byeSeen);
		TestHarness.assertTrue("ACK should be seen by proxy", ackSeen);
	}

	public void processRequest(RequestEvent requestEvent) {
		try {
			Request request = requestEvent.getRequest();
			SipProvider sipProvider = (SipProvider) requestEvent.getSource();
			if (request.getMethod().equals(Request.INVITE)) {
				inviteSeen = true;

				ListeningPoint lp = sipProvider
						.getListeningPoint(protocolObjects.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();

				//
				// Add a Route: header to 5080
				//
				SipURI sipUri = protocolObjects.addressFactory.createSipURI(
						"UA1", "127.0.0.1");
				sipUri.setPort(5080);
				sipUri.setLrParam();
				sipUri.setTransportParam( protocolObjects.transport );
				Address address = protocolObjects.addressFactory.createAddress(
						"client1", sipUri);
				RouteHeader rheader = protocolObjects.headerFactory
						.createRouteHeader(address);
				newRequest.addFirst(rheader);

				//
				// Add a Via header + Record-Route
				//
				ViaHeader viaHeader = protocolObjects.headerFactory
						.createViaHeader(host, port, protocolObjects.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();
				sipUri.setTransportParam(protocolObjects.transport);

				RecordRouteHeader recordRoute = protocolObjects.headerFactory
						.createRecordRouteHeader(address);
				newRequest.addHeader(recordRoute);
				ct1.setApplicationData(st);

				// Send the request out to the two listening point of the
				// client.
				ct1.sendRequest();

				TestHarness.assertNull(ct1.getDialog());
			} else if (request.getMethod().equals(Request.ACK)) {
				Request newRequest = (Request) request.clone();
				newRequest.removeFirst(RouteHeader.NAME);
				ViaHeader viaHeader = protocolObjects.headerFactory
						.createViaHeader(host, port, protocolObjects.transport,
								null);
				newRequest.addFirst(viaHeader);
				this.ackSeen = true;
				logger.debug("PROXY : sendingAck "  + newRequest);
				sipProvider.sendRequest(newRequest);
			} else {
				// Remove the topmost route header
				// The route header will make sure it gets to the right place.
				logger.debug("proxy: Got a request\n" + request);
				if (request.getMethod().equals(Request.BYE)) {
					this.byeSeen = true;
				}
				if (request.getMethod().equals(Request.INFO)) {
					this.infoCount++;
				}

				if (requestEvent.getServerTransaction() == null) {
					TestHarness.assertNull("Dialog should be null",
							requestEvent.getDialog());
					ServerTransaction stx = sipProvider
							.getNewServerTransaction(request);
					Request newRequest = (Request) request.clone();
					newRequest.removeFirst(RouteHeader.NAME);
					ViaHeader viaHeader = protocolObjects.headerFactory
							.createViaHeader(host, port,
									protocolObjects.transport, null);
					newRequest.addFirst(viaHeader);

					ClientTransaction ctx = sipProvider
							.getNewClientTransaction(newRequest);
					ctx.setApplicationData(stx);
					stx.setApplicationData(ctx);
					ctx.sendRequest();
				} else {
					logger.debug("Saw a retransmission? State = "
							+ requestEvent.getServerTransaction().getState());
				}
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			logger.error("Unexpected error forwarding request", ex);
			TestHarness.fail("Unexpected exception forwarding request");
		}

	}

	public void processResponse(ResponseEvent responseEvent) {
		try {
			Response response = responseEvent.getResponse();
			CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
			logger.debug("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;

			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.
				if ( st.getState() != TransactionState.TERMINATED)
				 st.sendResponse(newResponse);

				TestHarness.assertNull(st.getDialog());
			} 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
				SipProvider sipProvider = (SipProvider) responseEvent
						.getSource();
				sipProvider.sendResponse(newResponse);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			TestHarness.fail("unexpected exception",ex);
		}
	}

	public void processTimeout(TimeoutEvent timeoutEvent) {
		logger.error("Timeout occured");
		fail("unexpected event");
	}

	public void processIOException(IOExceptionEvent exceptionEvent) {
		logger.error("IOException occured");
		fail("unexpected exception io exception");
	}

	public SipProvider createSipProvider() {
		try {
			ListeningPoint listeningPoint = protocolObjects.sipStack
					.createListeningPoint(host, port, protocolObjects.transport);

			sipProvider = protocolObjects.sipStack
					.createSipProvider(listeningPoint);
			sipProvider.setAutomaticDialogSupportEnabled(false);
			return sipProvider;
		} catch (Exception ex) {
			logger.error(unexpectedException, ex);
			fail(unexpectedException);
			return null;
		}

	}

	public void processTransactionTerminated(
			TransactionTerminatedEvent transactionTerminatedEvent) {
		logger.debug("Transaction terminated event occured -- cleaning up");
	}

	public void processDialogTerminated(
			DialogTerminatedEvent dialogTerminatedEvent) {
		fail("unexpected event");
	}

	public Proxy(int myPort, ProtocolObjects protocolObjects) {
		this.port = myPort;
		this.protocolObjects = protocolObjects;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy