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

performance.b2bua.TestCall Maven / Gradle / Ivy

There is a newer version: 1.3.0-91
Show newest version
package performance.b2bua;

import gov.nist.javax.sip.ListeningPointImpl;
import gov.nist.javax.sip.header.Route;
import gov.nist.javax.sip.header.RouteList;
import gov.nist.javax.sip.header.Via;
import gov.nist.javax.sip.header.ViaList;
import gov.nist.javax.sip.message.SIPRequest;

import java.text.ParseException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Set;

import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.DialogState;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.SipProvider;
import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ContentLengthHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.Header;
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;

public class TestCall {
	
	private String localTag;
	private CallIdHeader outgoingDialogCallId;
	
	private SipProvider sipProvider;
	private MessageFactory messageFactory;
	private HeaderFactory headerFactory;
	private Dialog incomingDialog;
	private Dialog outgoingDialog;
	private ServerTransaction serverTransaction;
	
	public TestCall(String localTag, SipProvider sipProvider, HeaderFactory headerFactory, MessageFactory messageFactory) {
		this.localTag = localTag;
		this.sipProvider = sipProvider;
		this.messageFactory = messageFactory;
		this.headerFactory = headerFactory;
	}
	
	/**
	 * @return the incomingDialog
	 */
	public Dialog getIncomingDialog() {
		return incomingDialog;
	}
	
	/**
	 * @return the outgoingDialog
	 */
	public Dialog getOutgoingDialog() {
		return outgoingDialog;
	}
	
	public void processInvite(RequestEvent requestEvent) {
		//System.out.println("Got invite: "+requestEvent.getRequest());
		try {
			serverTransaction = requestEvent.getServerTransaction();
			if (serverTransaction == null) {
				try {
					serverTransaction = sipProvider.getNewServerTransaction(requestEvent.getRequest());
				}
				catch (Exception e) {
					e.printStackTrace();
					return;
				}
			}
			//serverTransaction.sendResponse(messageFactory.createResponse(100, requestEvent.getRequest()));
			setupIncomingDialog();
			forwardInvite();			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * @param serverTransaction2
	 * @return
	 * @throws SipException 
	 */
	private void setupIncomingDialog() throws SipException {
		this.incomingDialog = sipProvider.getNewDialog(serverTransaction);
		this.incomingDialog.setApplicationData(this);
	}
	
	/**
	 * @param incomingDialog2
	 * @return
	 * @throws SipException 
	 */
	private void forwardInvite() throws SipException {
		this.outgoingDialogCallId = sipProvider.getNewCallId();
		Request request = createRequest(serverTransaction.getRequest());
		ClientTransaction ct = sipProvider.getNewClientTransaction(request);
		this.outgoingDialog = sipProvider.getNewDialog(ct);
		this.outgoingDialog.setApplicationData(this);
		ct.sendRequest();
	}

	@SuppressWarnings("unchecked")
	private Request createRequest(Request origRequest) throws SipException {

		final SIPRequest request = (SIPRequest) origRequest.clone();

		try {
			request.getFromHeader().setTag(localTag);
		} catch (ParseException e1) {
			throw new SipException("failed to set local tag", e1);
		}

		final String transport = request.getTopmostViaHeader().getTransport();
		final ListeningPointImpl listeningPointImpl = (ListeningPointImpl) sipProvider.getListeningPoint(transport);

		final ViaList viaList = new ViaList();
		viaList.add((Via) listeningPointImpl.createViaHeader());
		request.setVia(viaList);
		
		try {
			request.setHeader(headerFactory.createMaxForwardsHeader(70));
		} catch (InvalidArgumentException e) {
			throw new SipException("Failed to create max forwards header",e);
		}
		request.setHeader((Header) outgoingDialogCallId.clone());
		// note: cseq will be set by dialog when sending
		// set contact if the original response had it
		if (origRequest.getHeader(ContactHeader.NAME) != null) {
			request.setHeader(listeningPointImpl.createContactHeader());
		}

		/*
		 * Route header fields of the upstream request MAY be copied in the
		 * downstream request, except the topmost Route header if it is under
		 * the responsibility of the B2BUA. Additional Route header fields MAY
		 * also be added to the downstream request.
		 */
		if (outgoingDialog == null || outgoingDialog.getState() == null) {
			// first request, no route available
			final RouteList routeList = request.getRouteHeaders();
			if (routeList != null) {
				final RouteHeader topRoute = routeList.get(0);
				final URI topRouteURI = topRoute.getAddress().getURI();
				if (topRouteURI.isSipURI()) {
					final SipURI topRouteSipURI = (SipURI) topRouteURI;
					if (topRouteSipURI.getHost().equals(listeningPointImpl.getIPAddress())
							&& topRouteSipURI.getPort() == listeningPointImpl.getPort()) {
						if (routeList.size() > 1) {
							routeList.remove(0);
						}
						else {
							request.removeHeader(RouteHeader.NAME);
						}					
					}
				}
			}			
		}
		else {
			// replace route in orig request with the one in dialog
			request.removeHeader(RouteHeader.NAME);
			final RouteList routeList = new RouteList();
			for (Iterator it = outgoingDialog.getRouteSet(); it.hasNext();) {
				Route route = it.next();				
				routeList.add(route);								
			}
			if (!routeList.isEmpty()) {
				request.addHeader(routeList);
			}
		}
		
		/*
		 * Record-Route header fields of the upstream request are not copied in
		 * the new downstream request, as Record-Route is only meaningful for
		 * the upstream dialog.
		 */
		request.removeHeader(RecordRouteHeader.NAME);

		return request;		
	}

	public void processAck(RequestEvent requestEvent) {
		// ignore
	}

	public void processBye(RequestEvent requestEvent) {
		try {
			requestEvent.getServerTransaction().sendResponse(messageFactory.createResponse(200, requestEvent.getRequest()));
			final Request request = createRequest(requestEvent.getRequest());
			final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
			outgoingDialog.sendRequest(ct);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void process180(ResponseEvent responseEvent) {
		try {
			forwardResponse(responseEvent.getResponse());
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @param responseEvent
	 * @throws InvalidArgumentException 
	 */
	@SuppressWarnings("unchecked")
	private void forwardResponse(Response receivedResponse) throws SipException, InvalidArgumentException {

		final ServerTransaction origServerTransaction = this.serverTransaction;	
		Response forgedResponse = null;
		
		try {
			forgedResponse = messageFactory.createResponse(receivedResponse.getStatusCode(), origServerTransaction.getRequest());
		} catch (ParseException e) {
			throw new SipException("Failed to forge message", e);
		}
		
		final DialogState dialogState = incomingDialog.getState();
		if ((dialogState == null || dialogState == DialogState.EARLY) && localTag != null && incomingDialog.isServer()) {
			// no tag set in the response, since the dialog creating transaction didn't had it
			try {
				((ToHeader)forgedResponse.getHeader(ToHeader.NAME)).setTag(localTag);
			} catch (ParseException e) {
				throw new SipException("Failed to set local tag", e);
			}
		}
		
		// copy headers 
		ListIterator lit = receivedResponse.getHeaderNames();
		String headerName = null;
		ListIterator
headersIterator = null; while (lit.hasNext()) { headerName = lit.next(); if (TestCall.getHeadersToOmmitOnResponseCopy().contains(headerName)) { continue; } else { forgedResponse.removeHeader(headerName); headersIterator = receivedResponse.getHeaders(headerName); while (headersIterator.hasNext()) { forgedResponse.addLast((Header)headersIterator.next().clone()); } } } // Copy content final byte[] rawOriginal = receivedResponse.getRawContent(); if (rawOriginal != null && rawOriginal.length != 0) { final byte[] copy = new byte[rawOriginal.length]; System.arraycopy(rawOriginal, 0, copy, 0, copy.length); try { forgedResponse.setContent(copy, (ContentTypeHeader) forgedResponse .getHeader(ContentTypeHeader.NAME)); } catch (ParseException e) { throw new SipException("Failed to copy content.",e); } } // set contact if the received response had it if (receivedResponse.getHeader(ContactHeader.NAME) != null) { final String transport = ((ViaHeader) forgedResponse.getHeader(ViaHeader.NAME)).getTransport(); forgedResponse.setHeader(((ListeningPointImpl)sipProvider.getListeningPoint(transport)).createContactHeader()); } origServerTransaction.sendResponse(forgedResponse); } public void process200(ResponseEvent responseEvent) { try { final CSeqHeader cSeqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); if (cSeqHeader.getMethod().equals(Request.INVITE)) { processInvite200(responseEvent,cSeqHeader); } else if (cSeqHeader.getMethod().equals(Request.BYE)) { processBye200(responseEvent); } else { System.err.println("Unexpected response: "+responseEvent.getResponse()); } } catch (Exception ex) { ex.printStackTrace(); } } /** * @param responseEvent * @throws SipException * @throws InvalidArgumentException */ private void processInvite200(ResponseEvent responseEvent,CSeqHeader cseq) throws InvalidArgumentException, SipException { // lets ack it ourselves to avoid UAS retransmissions due to // forwarding of this response and further UAC Ack // note that the app does not handles UAC ACKs final Request ack = responseEvent.getDialog().createAck(cseq.getSeqNumber()); responseEvent.getDialog().sendAck(ack); forwardResponse(responseEvent.getResponse()); } /** * @param responseEvent */ private void processBye200(ResponseEvent responseEvent) { // nothing to do } private static Set HEADERS_TO_OMMIT_ON_RESPONSE_COPY; private static Set getHeadersToOmmitOnResponseCopy() { if (HEADERS_TO_OMMIT_ON_RESPONSE_COPY == null) { final Set set = new HashSet(); set.add(RouteHeader.NAME); set.add(RecordRouteHeader.NAME); set.add(ViaHeader.NAME); set.add(CallIdHeader.NAME); set.add(CSeqHeader.NAME); set.add(ContactHeader.NAME); set.add(FromHeader.NAME); set.add(ToHeader.NAME); set.add(ContentLengthHeader.NAME); HEADERS_TO_OMMIT_ON_RESPONSE_COPY = Collections.unmodifiableSet(set); } return HEADERS_TO_OMMIT_ON_RESPONSE_COPY; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy