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

org.mobicents.servlet.sip.message.SipFactoryImpl Maven / Gradle / Ivy

There is a newer version: 4.0.128
Show newest version
/*
 * TeleStax, Open Source Cloud Communications
 * Copyright 2011-2014, Telestax Inc and individual contributors
 * by the @authors tag.
 *
 * This program is free software: you can redistribute it and/or modify
 * under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see 
 */

package org.mobicents.servlet.sip.message;

import gov.nist.javax.sip.header.HeaderFactoryExt;
import gov.nist.javax.sip.header.HeaderFactoryImpl;
import gov.nist.javax.sip.header.ims.PathHeader;
import gov.nist.javax.sip.message.MessageExt;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.sip.Address;
import javax.servlet.sip.AuthInfo;
import javax.servlet.sip.Parameterable;
import javax.servlet.sip.ServletParseException;
import javax.servlet.sip.SipApplicationSession;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipURI;
import javax.servlet.sip.URI;
import javax.servlet.sip.ar.SipApplicationRouterInfo;
import javax.servlet.sip.ar.SipApplicationRoutingDirective;
import javax.sip.ListeningPoint;
import javax.sip.PeerUnavailableException;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.address.AddressFactory;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ContentDispositionHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.Header;
import javax.sip.header.HeaderFactory;
import javax.sip.header.MaxForwardsHeader;
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 org.apache.log4j.Logger;
import org.mobicents.ha.javax.sip.SipLoadBalancer;
import org.mobicents.servlet.sip.JainSipUtils;
import org.mobicents.servlet.sip.address.AddressImpl;
import org.mobicents.servlet.sip.address.AddressImpl.ModifiableRule;
import org.mobicents.servlet.sip.address.GenericURIImpl;
import org.mobicents.servlet.sip.address.SipURIImpl;
import org.mobicents.servlet.sip.address.TelURLImpl;
import org.mobicents.servlet.sip.address.URIImpl;
import org.mobicents.servlet.sip.core.ApplicationRoutingHeaderComposer;
import org.mobicents.servlet.sip.core.MobicentsExtendedListeningPoint;
import org.mobicents.servlet.sip.core.MobicentsSipFactory;
import org.mobicents.servlet.sip.core.MobicentsSipServletMessageFactory;
import org.mobicents.servlet.sip.core.SipApplicationDispatcher;
import org.mobicents.servlet.sip.core.SipContext;
import org.mobicents.servlet.sip.core.SipNetworkInterfaceManager;
import org.mobicents.servlet.sip.core.dispatchers.MessageDispatcher;
import org.mobicents.servlet.sip.core.message.OutboundProxy;
import org.mobicents.servlet.sip.core.session.MobicentsSipApplicationSession;
import org.mobicents.servlet.sip.core.session.MobicentsSipApplicationSessionKey;
import org.mobicents.servlet.sip.core.session.MobicentsSipSession;
import org.mobicents.servlet.sip.core.session.MobicentsSipSessionKey;
import org.mobicents.servlet.sip.core.session.SessionManagerUtil;
import org.mobicents.servlet.sip.core.session.SipApplicationSessionKey;
import org.mobicents.servlet.sip.security.AuthInfoImpl;
import org.mobicents.servlet.sip.startup.StaticServiceHolder;

public class SipFactoryImpl implements MobicentsSipFactory,  Externalizable {	

	private static final long serialVersionUID = 1L;
	private static final Logger logger = Logger.getLogger(SipFactoryImpl.class
			.getCanonicalName());
	private static final String TAG_PARAM = "tag";
	private static final String METHOD_PARAM = "method";
	private static final String MADDR_PARAM = "maddr";
	private static final String TTL_PARAM = "ttl";
	private static final String TRANSPORT_PARAM = "transport";
	private static final String LR_PARAM = "lr";

	private boolean useLoadBalancer = false;
	private boolean useLoadBalancerForAllRequests = true;
	private boolean routeOrphanRequests = false;
	private SipLoadBalancer loadBalancerToUse = null;
	
	private static boolean initialized;
	public static AddressFactory addressFactory;
	public static HeaderFactory headerFactory;
	public static SipFactory sipFactory;
	public static MessageFactory messageFactory;
	
	private MobicentsSipServletMessageFactory mobicentsSipServletMessageFactory;

	public void initialize(String pathName, boolean prettyEncoding) {
		if (!initialized) {
			try {
				System.setProperty("gov.nist.core.STRIP_ADDR_SCOPES", "true");
				sipFactory = SipFactory.getInstance();
				sipFactory.setPathName(pathName);
				addressFactory = sipFactory.createAddressFactory();				
				headerFactory = sipFactory.createHeaderFactory();
				if(prettyEncoding) {
					((HeaderFactoryImpl)headerFactory).setPrettyEncoding(prettyEncoding);
				}
				messageFactory = sipFactory.createMessageFactory();
				initialized = true;
			} catch (PeerUnavailableException ex) {
				logger.error("Could not instantiate factories -- exitting", ex);
				throw new IllegalArgumentException("Cannot instantiate factories ", ex);
			}
		}
	}

	public static class NamesComparator implements Comparator, Serializable {		
		private static final long serialVersionUID = 1L;

		public int compare(String o1, String o2) {
			return o1.compareToIgnoreCase(o2);
		}
	}
	
	public static final Set FORBIDDEN_PARAMS = new HashSet();

	static {
		FORBIDDEN_PARAMS.add(TAG_PARAM);
		FORBIDDEN_PARAMS.add(METHOD_PARAM);
		FORBIDDEN_PARAMS.add(MADDR_PARAM);
		FORBIDDEN_PARAMS.add(TTL_PARAM);
		FORBIDDEN_PARAMS.add(TRANSPORT_PARAM);
		FORBIDDEN_PARAMS.add(LR_PARAM);
	}	

	private transient SipApplicationDispatcher sipApplicationDispatcher = null;
	
	public SipFactoryImpl() {}
	/**
	 * Dafault constructor
	 * @param sipApplicationDispatcher 
	 */
	public SipFactoryImpl(SipApplicationDispatcher sipApplicationDispatcher) {		
		this.sipApplicationDispatcher = sipApplicationDispatcher;
		mobicentsSipServletMessageFactory = initMobicentsSipServletMessageFactory();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createAddress(java.lang.String)
	 */
	public Address createAddress(String sipAddress)
			throws ServletParseException {
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Creating Address from [" + sipAddress + "]");
			}

			AddressImpl retval = new AddressImpl();
			retval.setValue(sipAddress);
			return retval;
		} catch (IllegalArgumentException e) {
			throw new ServletParseException(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createAddress(javax.servlet.sip.URI)
	 */
	public Address createAddress(URI uri) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating Address fromm URI[" + uri.toString()
					+ "]");
		}
		URIImpl uriImpl = (URIImpl) uri;
		return new AddressImpl(SipFactoryImpl.addressFactory
				.createAddress(uriImpl.getURI()), null, ModifiableRule.Modifiable);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createAddress(javax.servlet.sip.URI,
	 *      java.lang.String)
	 */
	public Address createAddress(URI uri, String displayName) {
		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Creating Address from URI[" + uri.toString()
						+ "] with display name[" + displayName + "]");
			}

			javax.sip.address.Address address = SipFactoryImpl.addressFactory
					.createAddress(((URIImpl) uri).getURI());
			address.setDisplayName(displayName);
			return new AddressImpl(address, null, ModifiableRule.Modifiable);

		} catch (ParseException e) {
			throw new IllegalArgumentException(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createApplicationSession()
	 */
	public SipApplicationSession createApplicationSession() {
		throw new UnsupportedOperationException("use createApplicationSession(SipContext sipContext) instead !");
	}
	
	/**
	 * Creates an application session associated with the context
	 * @param sipContext
	 * @return
	 */
	public MobicentsSipApplicationSession createApplicationSession(SipContext sipContext) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating new application session for sip context "+ sipContext.getApplicationName());
		}
		//call id not needed anymore since the sipappsessionkey is not a callid anymore but a random uuid
		SipApplicationSessionKey sipApplicationSessionKey = SessionManagerUtil.getSipApplicationSessionKey(
				sipContext.getApplicationName(), 
				null,
				null);		
		MobicentsSipApplicationSession sipApplicationSession = sipContext.getSipManager().getSipApplicationSession(
				sipApplicationSessionKey, true);
		
		if(StaticServiceHolder.sipStandardService.isHttpFollowsSip()) {
			String jvmRoute = StaticServiceHolder.sipStandardService.getJvmRoute();
			if(jvmRoute != null) {
				sipApplicationSession.setJvmRoute(jvmRoute);
			}
		}
			
		return sipApplicationSession.getFacade();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipApplicationSession,
	 *      java.lang.String, javax.servlet.sip.Address,
	 *      javax.servlet.sip.Address)
	 */
	public SipServletRequest createRequest(SipApplicationSession sipAppSession,
			String method, Address from, Address to, String handler, String originalCallId, String fromTagToUse) {
		if (logger.isDebugEnabled()) {
			logger
					.debug("Creating new SipServletRequest for SipApplicationSession["
							+ sipAppSession
							+ "] METHOD["
							+ method
							+ "] FROM_A[" + from + "] TO_A[" + to + "]");
		}

		validateCreation(method, sipAppSession);

		try { 
			//javadoc specifies that a copy of the address should be done hence the clone
			return createSipServletRequest(sipAppSession, method, (Address)from.clone(), (Address)to.clone(), handler, originalCallId, fromTagToUse);
		} catch (ServletParseException e) {
			logger.error("Error creating sipServletRequest", e);
			return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipApplicationSession,
	 *      java.lang.String, javax.servlet.sip.URI, javax.servlet.sip.URI)
	 */
	public SipServletRequest createRequest(SipApplicationSession sipAppSession,
			String method, URI from, URI to, String handler) {
		if (logger.isDebugEnabled()) {
			logger
					.debug("Creating new SipServletRequest for SipApplicationSession["
							+ sipAppSession
							+ "] METHOD["
							+ method
							+ "] FROM_URI[" + from + "] TO_URI[" + to + "]");
		}

		validateCreation(method, sipAppSession);

		//javadoc specifies that a copy of the uri should be done hence the clone
		Address toA = this.createAddress(to.clone());
		Address fromA = this.createAddress(from.clone());

		try {
			return createSipServletRequest(sipAppSession, method, fromA, toA, handler, null, null);
		} catch (ServletParseException e) {
			logger.error("Error creating sipServletRequest", e);
			return null;
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipApplicationSession,
	 *      java.lang.String, java.lang.String, java.lang.String)
	 */
	public SipServletRequest createRequest(SipApplicationSession sipAppSession,
			String method, String from, String to, String handler) throws ServletParseException {
		if (logger.isDebugEnabled()) {
			logger
					.debug("Creating new SipServletRequest for SipApplicationSession["
							+ sipAppSession
							+ "] METHOD["
							+ method
							+ "] FROM["
							+ from + "] TO[" + to + "]");
		}

		validateCreation(method, sipAppSession);

		Address toA = this.createAddress(to);
		Address fromA = this.createAddress(from);

		return createSipServletRequest(sipAppSession, method, fromA, toA, handler, null, null);

	}
        
        @Override 
        public SipServletRequest createRequestWithCallID(SipApplicationSession sipAppSession,
                        String method, Address from, Address to, String callID){
		if (logger.isDebugEnabled()) {
			logger
					.debug("Creating new SipServletRequest for SipApplicationSession["
							+ sipAppSession
							+ "] METHOD["
							+ method
							+ "] FROM_A[" + from + "] TO_A[" + to + "]");
		}

		validateCreation(method, sipAppSession);

		try { 
                        String handler = ((MobicentsSipApplicationSession)sipAppSession).getCurrentRequestHandler();
			//javadoc specifies that a copy of the address should be done hence the clone
			return createSipServletRequest(sipAppSession, method, (Address)from.clone(), (Address)to.clone(), handler, callID, null);
		} catch (ServletParseException e) {
			logger.error("Error creating sipServletRequest", e);
			return null;
		}
        }

        @Override 
        public SipServletRequest createRequestWithCallID(SipApplicationSession sipAppSession,
                        String method, String from, String to, String callID) throws ServletParseException{
		if (logger.isDebugEnabled()) {
			logger
					.debug("Creating new SipServletRequest for SipApplicationSession["
							+ sipAppSession
							+ "] METHOD["
							+ method
							+ "] FROM["
							+ from + "] TO[" + to + "]");
		}

		validateCreation(method, sipAppSession);

		Address toA = this.createAddress(to);
		Address fromA = this.createAddress(from);
                String handler = ((MobicentsSipApplicationSession)sipAppSession).getCurrentRequestHandler();
		return createSipServletRequest(sipAppSession, method, fromA, toA, handler, callID, null);
        }

        @Override 
        public SipServletRequest createRequestWithCallID(SipApplicationSession sipAppSession,
                        String method, URI from, URI to, String callID){
		if (logger.isDebugEnabled()) {
			logger
					.debug("Creating new SipServletRequest for SipApplicationSession["
							+ sipAppSession
							+ "] METHOD["
							+ method
							+ "] FROM_URI[" + from + "] TO_URI[" + to + "]");
		}

		validateCreation(method, sipAppSession);

		//javadoc specifies that a copy of the uri should be done hence the clone
		Address toA = this.createAddress(to.clone());
		Address fromA = this.createAddress(from.clone());

		try {
                        String handler = ((MobicentsSipApplicationSession)sipAppSession).getCurrentRequestHandler();
			return createSipServletRequest(sipAppSession, method, fromA, toA, handler, callID, null);
		} catch (ServletParseException e) {
			logger.error("Error creating sipServletRequest", e);
			return null;
		}       
        }          
        
	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipServletRequest,
	 *      boolean)
	 */
	public SipServletRequest createRequest(SipServletRequest origRequest,
			boolean sameCallId) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating SipServletRequest from original request["
					+ origRequest + "] with same call id[" + sameCallId + "]");
		}
	    
		final SipServletRequestImpl origRequestImpl = (SipServletRequestImpl) origRequest;
		final MobicentsSipApplicationSession originalAppSession = (MobicentsSipApplicationSession) origRequestImpl.getSipApplicationSession(false);		
		if (originalAppSession == null) {
			throw new IllegalStateException("original request's app session does not exists");
		}			
		final MobicentsSipSession originalSession = origRequestImpl.getSipSession();
		final Request newRequest = (Request) origRequestImpl.message.clone();
		((MessageExt)newRequest).setApplicationData(null);
		//removing the via header from original request
		newRequest.removeHeader(ViaHeader.NAME);	
		
		// cater to http://code.google.com/p/sipservlets/issues/detail?id=31 to be able to set the rport in applications
		final SipApplicationDispatcher sipApplicationDispatcher = getSipApplicationDispatcher();
		final String branch = JainSipUtils.createBranch(originalAppSession.getKey().getId(),  sipApplicationDispatcher.getHashFromApplicationName(originalAppSession.getKey().getApplicationName()));
		ViaHeader viaHeader = JainSipUtils.createViaHeader(
				getSipNetworkInterfaceManager(), newRequest, branch, null);
		newRequest.addHeader(viaHeader);
		
		final FromHeader newFromHeader = (FromHeader) newRequest.getHeader(FromHeader.NAME); 
		
		//assign a new from tag
		newFromHeader.removeParameter("tag");
		//remove the to tag
		((ToHeader) newRequest.getHeader(ToHeader.NAME))
				.removeParameter("tag");
		// Remove the route header ( will point to us ).
		// commented as per issue 649
//		newRequest.removeHeader(RouteHeader.NAME);
		
		// Remove the record route headers. This is a new call leg.
		newRequest.removeHeader(RecordRouteHeader.NAME);
		
		//For non-REGISTER requests, the Contact header field is not copied 
		//but is populated by the container as usual
		if(!Request.REGISTER.equalsIgnoreCase(newRequest.getMethod())) {
			try {
				//For non-REGISTER requests, the Contact header field is not copied
				//but is populated by the container as usual
				if(!Request.REGISTER.equalsIgnoreCase(newRequest.getMethod())) {
					
			
					//Adding default contact header for specific methods only
					if(JainSipUtils.CONTACT_HEADER_METHODS.contains(newRequest.getMethod())) {
						String fromName = null;
						String displayName = ((MessageExt)newRequest).getFromHeader().getAddress().getDisplayName();
						if(newRequest.getHeader(ContactHeader.NAME) != null && 
							((ContactHeader)newRequest.getHeader(ContactHeader.NAME)).getAddress().getURI() instanceof javax.sip.address.SipURI) {
							fromName = ((javax.sip.address.SipURI)((MessageExt)newRequest).getFromHeader().getAddress().getURI()).getUser();
						}
						// Create the contact name address.
						ContactHeader contactHeader = null;
						// if a sip load balancer is present in front of the server, the contact header is the one from the sip lb
						// so that the subsequent requests can be failed over
						if(fromName != null) {
							if(useLoadBalancer) {
								javax.sip.address.SipURI sipURI = addressFactory.createSipURI(fromName, loadBalancerToUse.getAddress().getHostAddress());
								sipURI.setHost(loadBalancerToUse.getAddress().getHostAddress());
								sipURI.setPort(loadBalancerToUse.getSipPort());
								sipURI.setTransportParam(JainSipUtils.findTransport(newRequest));
								javax.sip.address.Address contactAddress = addressFactory.createAddress(sipURI);
								if(displayName != null && displayName.length() > 0) {
									contactAddress.setDisplayName(displayName);
								}
								contactHeader = headerFactory.createContactHeader(contactAddress);
							} else {
								contactHeader = JainSipUtils.createContactHeader(getSipNetworkInterfaceManager(), newRequest, displayName, fromName, null);
							}
						} else {
							if(logger.isDebugEnabled()) {
								logger.debug("Unable to create Contact Header. It will be added later on send.");
							}
						}
			
						newRequest.removeHeader(ContactHeader.NAME);
						if(contactHeader != null) {
							newRequest.addHeader(contactHeader);
						}
					} else {
						newRequest.removeHeader(ContactHeader.NAME);
					}
				}
			} catch (Exception ex) {
				logger.warn("Unable to create Contact Header. It will be added later on send.", ex);
			}
		}		
		try {
			if(!sameCallId) {
				//Creating new call id
				final Iterator listeningPointsIterator = getSipNetworkInterfaceManager().getExtendedListeningPoints();				
				if(!listeningPointsIterator.hasNext()) {				
					throw new IllegalStateException("There is no SIP connectors available to create the request");
				}
				final MobicentsExtendedListeningPoint extendedListeningPoint = listeningPointsIterator.next();
				final CallIdHeader callIdHeader = sipApplicationDispatcher.getCallId(extendedListeningPoint, null);
				newRequest.setHeader(callIdHeader);
				if(logger.isDebugEnabled()) {
					logger.debug("not reusing same call id, new call id is " + callIdHeader);
				}
			} else {
				if(logger.isDebugEnabled()) {
					logger.debug("reusing same call id = " + ((MessageExt)newRequest).getCallIdHeader().getCallId());
				}
			}
									
			newFromHeader.setTag(ApplicationRoutingHeaderComposer.getHash(getSipApplicationDispatcher(), originalAppSession.getKey().getApplicationName(), originalAppSession.getKey().getId()));
			
			final MobicentsSipSessionKey key = SessionManagerUtil.getSipSessionKey(originalAppSession.getKey().getId(), originalAppSession.getKey().getApplicationName(), newRequest, false);
			final MobicentsSipSession session = originalAppSession.getSipContext().getSipManager().getSipSession(key, true, this, originalAppSession);			
			if(originalSession != null) {
				session.setHandler(originalSession.getHandler());
			} else if(originalAppSession.getCurrentRequestHandler() != null) {
				session.setHandler(originalAppSession.getCurrentRequestHandler());
			}
			
			final SipServletRequestImpl newSipServletRequest = (SipServletRequestImpl) mobicentsSipServletMessageFactory.createSipServletRequest(
					newRequest,
					session, 
					null, 
					null, 
					JainSipUtils.DIALOG_CREATING_METHODS.contains(newRequest.getMethod()));			
			//JSR 289 Section 15.1.6
			newSipServletRequest.setRoutingDirective(SipApplicationRoutingDirective.CONTINUE, origRequest);
			
			if(logger.isDebugEnabled()) {
				logger.debug("newSipServletRequest = " + newSipServletRequest);
			}	
			
			return newSipServletRequest;
		} catch (Exception ex) {
			logger.error("Unexpected exception ", ex);
			throw new IllegalArgumentException(
					"Illegal arg ecnountered while creatigng b2bua", ex);
		}			
	}
        
	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.sip.SipFactory#createSipURI(java.lang.String,
	 *      java.lang.String)
	 */
	public SipURI createSipURI(String user, String host) {		
		if (logger.isDebugEnabled()) {
			logger.debug("Creating SipURI from USER[" + user + "] HOST[" + host
					+ "]");
		}		
		// Fix for http://code.google.com/p/sipservlets/issues/detail?id=145
		if(user != null && user.trim().isEmpty()) {
			user = null;
		}
		try {
			return new SipURIImpl(SipFactoryImpl.addressFactory.createSipURI(
					user, host), ModifiableRule.Modifiable);
		} catch (ParseException e) {
			logger.error("couldn't parse the SipURI from USER[" + user
					+ "] HOST[" + host + "]", e);
			throw new IllegalArgumentException("Could not create SIP URI user = " + user + " host = " + host);
		}
	}

	public URI createURI(String uri) throws ServletParseException {
//		if(!checkScheme(uri)) {
//			// testCreateProxyBranches101 needs this to be IllegalArgumentExcpetion, but the test is wrong
//			throw new ServletParseException("The uri " + uri + " is not valid");
//		}
		try {
			javax.sip.address.URI jainUri = SipFactoryImpl.addressFactory
					.createURI(uri);
			if (jainUri instanceof javax.sip.address.SipURI) {
				return new SipURIImpl(
						(javax.sip.address.SipURI) jainUri, ModifiableRule.Modifiable);
			} else if (jainUri instanceof javax.sip.address.TelURL) {
				return new TelURLImpl(
						(javax.sip.address.TelURL) jainUri);
			} else {
				return new GenericURIImpl(jainUri);
			}
		} catch (ParseException ex) {
			throw new ServletParseException("Bad param " + uri, ex);
		}
	}

	// ------------ HELPER METHODS
	// -------------------- createRequest
	/**
	 * Does basic check for illegal methods, wrong state, if it finds, it throws
	 * exception
	 * 
	 */
	private static void validateCreation(String method, SipApplicationSession app) {

		if (method.equals(Request.ACK)) {
			throw new IllegalArgumentException(
					"Wrong method to create request with[" + Request.ACK + "]!");
		}
		if (method.equals(Request.PRACK)) {
			throw new IllegalArgumentException(
					"Wrong method to create request with[" + Request.PRACK + "]!");
		}
		if (method.equals(Request.CANCEL)) {
			throw new IllegalArgumentException(
					"Wrong method to create request with[" + Request.CANCEL
							+ "]!");
		}
		if (!((MobicentsSipApplicationSession)app).isValidInternal()) {
			throw new IllegalArgumentException(
					"Cant associate request with invalidaded sip session application!");
		}

	}

	/**
	 * This method actually does create javax.sip.message.Request, dialog(if
	 * method is INVITE or SUBSCRIBE), ctx and wraps this in new sipsession
	 * 
	 * @param sipAppSession
	 * @param method
	 * @param from
	 * @param to
	 * @param originalCallId 
	 * @return
	 */
	private SipServletRequest createSipServletRequest(
			SipApplicationSession sipAppSession, String method, Address from,
			Address to, String handler, String originalCallId, String fromTagToUse) throws ServletParseException {
		
		MobicentsSipApplicationSession mobicentsSipApplicationSession = (MobicentsSipApplicationSession) sipAppSession;
		
		// the request object with method, request URI, and From, To, Call-ID,
		// CSeq, Route headers filled in.
		Request requestToWrap = null;

		ContactHeader contactHeader = null;
		ToHeader toHeader = null;
		FromHeader fromHeader = null;
		CSeqHeader cseqHeader = null;
		CallIdHeader callIdHeader = null;
		MaxForwardsHeader maxForwardsHeader = null;		

		// FIXME: Is this nough?
		// We need address from which this will be sent, also this one will be
		// default for contact and via
		String transport = ListeningPoint.UDP;

		// LETS CREATE OUR HEADERS			
		javax.sip.address.Address fromAddress = null;
		try {
			// Issue 676 : Any component of the from and to URIs not allowed in the context of
			// SIP From and To headers are removed from the copies [refer Table 1, Section
			// 19.1.1, RFC3261]
			for(String param : FORBIDDEN_PARAMS) {
				from.getURI().removeParameter(param);	
			}
			
			// Issue 676 : from tags not removed so removing the tag
			from.removeParameter(TAG_PARAM);
			
			fromAddress = SipFactoryImpl.addressFactory
					.createAddress(((URIImpl)from.getURI()).getURI());
			fromAddress.setDisplayName(from.getDisplayName());		
			
			fromHeader = SipFactoryImpl.headerFactory.createFromHeader(fromAddress, null);			
		} catch (Exception pe) {
			throw new ServletParseException("Impossoible to parse the given From " + from.toString(), pe);
		}
		javax.sip.address.Address toAddress = null; 
		try{
			// Issue 676 : Any component of the from and to URIs not allowed in the context of
			// SIP From and To headers are removed from the copies [refer Table 1, Section
			// 19.1.1, RFC3261]
			for(String param : FORBIDDEN_PARAMS) {
				to.getURI().removeParameter(param);	
			}
			// Issue 676 : to tags not removed so removing the tag
			to.removeParameter(TAG_PARAM);
			
			toAddress = SipFactoryImpl.addressFactory
				.createAddress(((URIImpl)to.getURI()).getURI());
			
			toAddress.setDisplayName(to.getDisplayName());

			toHeader = SipFactoryImpl.headerFactory.createToHeader(toAddress, null);										
		} catch (Exception pe) {
			throw new ServletParseException("Impossoible to parse the given To " + to.toString(), pe);
		}
		try {
			cseqHeader = SipFactoryImpl.headerFactory.createCSeqHeader(1L, method);
			// Fix provided by Hauke D. Issue 411
			MobicentsSipApplicationSessionKey sipApplicationSessionKey = mobicentsSipApplicationSession.getKey();
//			if(sipApplicationSessionKey.isAppGeneratedKey()) {
			if(originalCallId == null) {
				final Iterator listeningPointsIterator = getSipNetworkInterfaceManager().getExtendedListeningPoints();				
				if(listeningPointsIterator.hasNext()) {
					callIdHeader = getSipApplicationDispatcher().getCallId(listeningPointsIterator.next(), null);
				} else {
					throw new IllegalStateException("There is no SIP connectors available to create the request");
				}
			} else {
				callIdHeader = getSipApplicationDispatcher().getCallId(null, originalCallId);
			}
//			} else {
//				callIdHeader = SipFactoryImpl.headerFactory.createCallIdHeader(
//						sipApplicationSessionKey.getId());
//			}
			maxForwardsHeader = SipFactoryImpl.headerFactory
					.createMaxForwardsHeader(JainSipUtils.MAX_FORWARD_HEADER_VALUE);
			URIImpl requestURI = (URIImpl)to.getURI().clone();

			// copying address params into headers.
			// commented out because of Issue 1105
//			Iterator keys = to.getParameterNames();
//
//			while (keys.hasNext()) {
//				String key = keys.next();				
//				toHeader.setParameter(key, to.getParameter(key));
//			}
//
//			keys = from.getParameterNames();
//
//			while (keys.hasNext()) {
//				String key = keys.next();				
//				fromHeader.setParameter(key, from.getParameter(key));
//			}
			//Issue 112 by folsson : no via header to add will be added when the request will be sent out
			List
viaHeaders = new ArrayList
(); requestToWrap = SipFactoryImpl.messageFactory.createRequest( requestURI.getURI(), method, callIdHeader, cseqHeader, fromHeader, toHeader, viaHeaders, maxForwardsHeader); //Adding default contact header for specific methods only if(JainSipUtils.CONTACT_HEADER_METHODS.contains(method)) { String fromName = null; String displayName = fromHeader.getAddress().getDisplayName(); if(fromHeader.getAddress().getURI() instanceof javax.sip.address.SipURI) { fromName = ((javax.sip.address.SipURI)fromHeader.getAddress().getURI()).getUser(); } // Create the contact name address. contactHeader = null; // if a sip load balancer is present in front of the server, the contact header is the one from the sip lb // so that the subsequent requests can be failed over if(useLoadBalancer) { javax.sip.address.SipURI sipURI = SipFactoryImpl.addressFactory.createSipURI(fromName, loadBalancerToUse.getAddress().getHostAddress()); sipURI.setHost(loadBalancerToUse.getAddress().getHostAddress()); sipURI.setPort(loadBalancerToUse.getSipPort()); sipURI.setTransportParam(transport); javax.sip.address.Address contactAddress = SipFactoryImpl.addressFactory.createAddress(sipURI); if(displayName != null && displayName.length() > 0) { contactAddress.setDisplayName(displayName); } contactHeader = SipFactoryImpl.headerFactory.createContactHeader(contactAddress); } else { contactHeader = JainSipUtils.createContactHeader(getSipNetworkInterfaceManager(), requestToWrap, displayName, fromName, null); } } // Add all headers if(contactHeader != null) { requestToWrap.addHeader(contactHeader); } if(fromTagToUse == null) { fromHeader.setTag(ApplicationRoutingHeaderComposer.getHash(sipApplicationDispatcher, sipAppSession.getApplicationName(), sipApplicationSessionKey.getId())); } else { fromHeader.setTag(fromTagToUse); } MobicentsSipSessionKey key = SessionManagerUtil.getSipSessionKey( mobicentsSipApplicationSession.getKey().getId(), mobicentsSipApplicationSession.getKey().getApplicationName(), requestToWrap, false); MobicentsSipSession session = mobicentsSipApplicationSession.getSipContext().getSipManager(). getSipSession(key, true, this, mobicentsSipApplicationSession); session.setHandler(handler); session.setLocalParty(new AddressImpl(fromAddress, null, ModifiableRule.NotModifiable)); session.setRemoteParty(new AddressImpl(toAddress, null, ModifiableRule.NotModifiable)); // cater to http://code.google.com/p/sipservlets/issues/detail?id=31 to be able to set the rport in applications final SipApplicationDispatcher sipApplicationDispatcher = getSipApplicationDispatcher(); final String branch = JainSipUtils.createBranch(sipApplicationSessionKey.getId(), sipApplicationDispatcher.getHashFromApplicationName(sipApplicationSessionKey.getApplicationName())); ViaHeader viaHeader = JainSipUtils.createViaHeader( getSipNetworkInterfaceManager(), requestToWrap, branch, session.getOutboundInterface()); requestToWrap.addHeader(viaHeader); SipServletRequest retVal = (SipServletRequestImpl) mobicentsSipServletMessageFactory.createSipServletRequest( requestToWrap, session, null, null, JainSipUtils.DIALOG_CREATING_METHODS.contains(method)); return retVal; } catch (Exception e) { throw new IllegalStateException("Error creating sipServletRequest", e); } } /** * {@inheritDoc} */ public Parameterable createParameterable(String value) throws ServletParseException { try { Header header = SipFactoryImpl.headerFactory.createHeader(ContactHeader.NAME, value); return SipServletMessageImpl.createParameterable(header, SipServletMessageImpl.getFullHeaderName(header.getName()), true); } catch (ParseException e) { try { Header header = SipFactoryImpl.headerFactory.createHeader(ContentTypeHeader.NAME, value); return SipServletMessageImpl.createParameterable(header, SipServletMessageImpl.getFullHeaderName(header.getName()), true); } catch (ParseException pe) { // Contribution from Nishihara, Naoki from Japan for Issue http://code.google.com/p/mobicents/issues/detail?id=1856 // Cannot create a parameterable header for Session-Expires try { Header header = SipFactoryImpl.headerFactory.createHeader(ContentDispositionHeader.NAME, value); return SipServletMessageImpl.createParameterable(header, SipServletMessageImpl.getFullHeaderName(header.getName()), true); } catch (ParseException pe2) { throw new ServletParseException("Impossible to parse the following parameterable "+ value , pe2); } } } } /** * {@inheritDoc} */ public SipApplicationRouterInfo getNextInterestedApplication(SipServletRequestImpl sipServletRequestImpl) { return sipApplicationDispatcher.getNextInterestedApplication(sipServletRequestImpl); } /* * (non-Javadoc) * @see javax.servlet.sip.SipFactory#createApplicationSessionByAppName(java.lang.String) */ public SipApplicationSession createApplicationSessionByAppName( String sipAppName, boolean isContainerManaged) { if (logger.isDebugEnabled()) { logger.debug("Creating new application session for application name " + sipAppName); } SipContext sipContext = sipApplicationDispatcher.findSipApplication(sipAppName); if(sipContext == null) { throw new IllegalArgumentException("The specified application "+sipAppName+" is not currently deployed"); } MobicentsSipApplicationSession sipApplicationSession = createApplicationSession(sipContext); // make sure to acquire this app session and add it to the set of app sessions we monitor in the context of the application // to release them all when we exit application code sipContext.enterSipApp(sipApplicationSession, null, true, isContainerManaged); return sipApplicationSession; } /* * (non-Javadoc) * @see javax.servlet.sip.SipFactory#createApplicationSessionByKey(java.lang.String) */ public SipApplicationSession createApplicationSessionByKey( String sipApplicationKey) { // should not be called directly, should be called through the facade object only return null; } /* * (non-Javadoc) * @see javax.servlet.sip.SipFactory#createAuthInfo() */ public AuthInfo createAuthInfo() { return new AuthInfoImpl(); } /** * @return the sipApplicationDispatcher */ public SipApplicationDispatcher getSipApplicationDispatcher() { if(sipApplicationDispatcher == null) { sipApplicationDispatcher = StaticServiceHolder.sipStandardService.getSipApplicationDispatcher(); } return sipApplicationDispatcher; } /** * @param sipApplicationDispatcher the sipApplicationDispatcher to set */ public void setSipApplicationDispatcher( SipApplicationDispatcher sipApplicationDispatcher) { this.sipApplicationDispatcher = sipApplicationDispatcher; } /** * Retrieve the manager for the sip network interfaces * @return the manager for the sip network interfaces */ public SipNetworkInterfaceManager getSipNetworkInterfaceManager() { return sipApplicationDispatcher.getSipNetworkInterfaceManager(); } /** * @return the loadBalancerToUse */ public SipLoadBalancer getLoadBalancerToUse() { return loadBalancerToUse; } /** * @param loadBalancerToUse the loadBalancerToUse to set */ public void setLoadBalancerToUse(SipLoadBalancer loadBalancerToUse) { if(loadBalancerToUse == null) { useLoadBalancer = false; } else { useLoadBalancer = true; } this.loadBalancerToUse = loadBalancerToUse; if(logger.isInfoEnabled()) { logger.info("Load Balancer to Use " + loadBalancerToUse); } } /** * @return the useLoadBalancer */ public boolean isUseLoadBalancer() { return useLoadBalancer; } /** * * @param request * @throws ParseException */ public void addLoadBalancerRouteHeader(Request request, MobicentsExtendedListeningPoint mobicentsExtendedListeningPoint) { try { String transport = JainSipUtils.findTransport(request); String host = null; int port = -1; OutboundProxy proxy = StaticServiceHolder.sipStandardService.getOutboundProxy(); if(proxy == null) { // if(transport.equalsIgnoreCase("ws") || transport.equalsIgnoreCase("wss")){ // if(logger.isDebugEnabled()) { // logger.debug("This is a WebSocket request through LB, no need to add Route header"); // } // return; // } else { if(mobicentsExtendedListeningPoint.getLoadBalancer() == null) { host = loadBalancerToUse.getAddress().getHostAddress(); port = loadBalancerToUse.getSipPort(); if(logger.isDebugEnabled()) { logger.debug("Using global load balancer " + host + ":" + port); } } else { host = mobicentsExtendedListeningPoint.getLoadBalancer().getAddress().getHostAddress(); port = mobicentsExtendedListeningPoint.getLoadBalancer().getSipPort(); if(logger.isDebugEnabled()) { logger.debug("Using specifc load balancer " + host + ":" + port + " from listening Point " + mobicentsExtendedListeningPoint); } } // } } else { host = proxy.getHost(); port = proxy.getPort(); } javax.sip.address.SipURI sipUri = SipFactoryImpl.addressFactory.createSipURI(null, host); sipUri.setPort(port); sipUri.setLrParam(); sipUri.setTransportParam(transport); MobicentsExtendedListeningPoint listeningPoint = mobicentsExtendedListeningPoint; if(mobicentsExtendedListeningPoint == null) { listeningPoint = getSipNetworkInterfaceManager().findMatchingListeningPoint(transport, false); if (logger.isDebugEnabled()) { logger.debug("mobicentsExtendedListeningPoint was null, found a listening point to use " + listeningPoint); } } boolean usePublicAddress = JainSipUtils.findUsePublicAddress(getSipNetworkInterfaceManager(), request, listeningPoint); String nodeHost= listeningPoint.getHost(usePublicAddress); if (logger.isDebugEnabled()) { logger.debug("usePublicAddress" + usePublicAddress + ", nodeHost=" + nodeHost + " nodePort" + listeningPoint.getPort()); } sipUri.setParameter(MessageDispatcher.ROUTE_PARAM_NODE_HOST, nodeHost); sipUri.setParameter(MessageDispatcher.ROUTE_PARAM_NODE_PORT, "" + listeningPoint.getPort()); javax.sip.address.Address routeAddress = SipFactoryImpl.addressFactory.createAddress(sipUri); RouteHeader routeHeader = SipFactoryImpl.headerFactory.createRouteHeader(routeAddress); request.addFirst(routeHeader); if(Request.REGISTER.equalsIgnoreCase(request.getMethod())) { PathHeader pathHeader = ((HeaderFactoryExt)SipFactoryImpl.headerFactory).createPathHeader(routeAddress); request.addFirst(pathHeader); } } catch (ParseException e) { //this should never happen throw new IllegalArgumentException("Impossible to set the Load Balancer Route Header !", e); } catch (SipException e) { //this should never happen throw new IllegalArgumentException("Impossible to set the Load Balancer Route Header !", e); } } public void addIpLoadBalancerRouteHeader(Request request, String lbhost, int lbport) { try { String host = null; int port = -1; OutboundProxy proxy = StaticServiceHolder.sipStandardService.getOutboundProxy(); if(proxy == null) { host = lbhost; port = lbport; } else { host = proxy.getHost(); port = proxy.getPort(); } javax.sip.address.SipURI sipUri = SipFactoryImpl.addressFactory.createSipURI(null, host); sipUri.setPort(port); sipUri.setLrParam(); String transport = JainSipUtils.findTransport(request); sipUri.setTransportParam(transport); MobicentsExtendedListeningPoint listeningPoint = getSipNetworkInterfaceManager().findMatchingListeningPoint(transport, false); sipUri.setParameter(MessageDispatcher.ROUTE_PARAM_NODE_HOST, listeningPoint.getHost(JainSipUtils.findUsePublicAddress(getSipNetworkInterfaceManager(), request, listeningPoint))); sipUri.setParameter(MessageDispatcher.ROUTE_PARAM_NODE_PORT, "" + listeningPoint.getPort()); javax.sip.address.Address routeAddress = SipFactoryImpl.addressFactory.createAddress(sipUri); RouteHeader routeHeader = SipFactoryImpl.headerFactory.createRouteHeader(routeAddress); request.addFirst(routeHeader); } catch (ParseException e) { //this should never happen throw new IllegalArgumentException("Impossible to set the Load Balancer Route Header !", e); } catch (SipException e) { //this should never happen throw new IllegalArgumentException("Impossible to set the Load Balancer Route Header !", e); } } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { useLoadBalancer = in.readBoolean(); if(useLoadBalancer) { loadBalancerToUse = (SipLoadBalancer) in.readObject(); } if(mobicentsSipServletMessageFactory == null) { mobicentsSipServletMessageFactory = initMobicentsSipServletMessageFactory(); } } public void writeExternal(ObjectOutput out) throws IOException { out.writeBoolean(useLoadBalancer); if(useLoadBalancer) { out.writeObject(loadBalancerToUse); } } public boolean isRouteOrphanRequests() { return routeOrphanRequests; } public void setRouteOrphanRequests(boolean routeOrphanRequets) { this.routeOrphanRequests = routeOrphanRequets; } @Override public SipServletRequest createRequest(SipApplicationSession appSession, String method, Address from, Address to) { throw new UnsupportedOperationException("Use the one createRequest(SipApplicationSession appSession, String method, Address from, Address to, String handler) method instead"); } @Override public SipServletRequest createRequest(SipApplicationSession appSession, String method, String from, String to) throws ServletParseException { throw new UnsupportedOperationException("Use the one createRequest(SipApplicationSession appSession, String method, String from, String to, String handler) method instead"); } @Override public SipServletRequest createRequest(SipApplicationSession appSession, String method, URI from, URI to) { throw new UnsupportedOperationException("Use the one createRequest(SipApplicationSession appSession, String method, URI from, URI to, String handler) method instead"); } /* (non-Javadoc) * @see org.mobicents.servlet.sip.core.MobicentsSipFactoryImpl#getAddressFactory() */ public AddressFactory getAddressFactory() { return addressFactory; } /* (non-Javadoc) * @see org.mobicents.servlet.sip.core.MobicentsSipFactoryImpl#getHeaderFactory() */ public HeaderFactory getHeaderFactory() { return headerFactory; } /* (non-Javadoc) * @see org.mobicents.servlet.sip.core.MobicentsSipFactoryImpl#getMessageFactory() */ public MessageFactory getMessageFactory() { return messageFactory; } /* (non-Javadoc) * @see org.mobicents.servlet.sip.core.MobicentsSipFactoryImpl#getSipFactory() */ public SipFactory getJainSipFactory() { return sipFactory; } @Override public MobicentsSipServletMessageFactory getMobicentsSipServletMessageFactory() { return mobicentsSipServletMessageFactory; } protected MobicentsSipServletMessageFactory initMobicentsSipServletMessageFactory() { MobicentsSipServletMessageFactory factory = null; try { factory = (MobicentsSipServletMessageFactory) Class.forName(StaticServiceHolder.sipStandardService.getMobicentsSipServletMessageFactoryClassName()).newInstance(); factory.setMobicentsSipFactory(this); } catch (InstantiationException e) { throw new IllegalArgumentException("Impossible to load the MobicentsSipServletMessageFactory ",e); } catch (IllegalAccessException e) { throw new IllegalArgumentException("Impossible to load the MobicentsSipServletMessageFactory ",e); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Impossible to load the MobicentsSipServletMessageFactory ",e); } return factory; } @Override public SipApplicationSession createApplicationSession(boolean managed) { throw new UnsupportedOperationException("use createApplicationSession(SipContext sipContext) instead !"); } @Override public SipApplicationSession createApplicationSessionByKey( String sipApplicationKey, boolean managed) { throw new UnsupportedOperationException("use createApplicationSession(SipContext sipContext) instead !"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy