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

android.gov.nist.javax.sip.stack.DefaultRouter Maven / Gradle / Ivy

There is a newer version: 1.3.0-91
Show newest version
/*
 * Conditions Of Use
 *
 * This software was developed by employees of the National Institute of
 * Standards and Technology (NIST), an agency of the Federal Government.
 * Pursuant to title 15 Untied States Code Section 105, works of NIST
 * employees are not subject to copyright protection in the United States
 * and are considered to be in the public domain.  As a result, a formal
 * license is not needed to use the software.
 *
 * This software is provided by NIST as a service and is expressly
 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
 * AND DATA ACCURACY.  NIST does not warrant or make any representations
 * regarding the use of the software or the results thereof, including but
 * not limited to the correctness, accuracy, reliability or usefulness of
 * the software.
 *
 * Permission to use this software is contingent upon your acceptance
 * of the terms of this agreement
 *
 * .
 *
 */
/*******************************************************************************
 * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).       *
 ******************************************************************************/
package android.gov.nist.javax.sip.stack;

import android.gov.nist.javax.sip.message.*;
import android.gov.nist.javax.sip.address.*;
import android.gov.nist.javax.sip.header.*;
import android.gov.nist.javax.sip.*;
import android.gov.nist.core.*;
import android.gov.nist.core.net.AddressResolver;

import android.javax.sip.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

import android.javax.sip.header.RouteHeader;
import android.javax.sip.header.ViaHeader;
import android.javax.sip.message.*;
import android.javax.sip.address.*;

/*
 * Bug reported by Will Scullin -- maddr was being ignored when routing
 * requests. Bug reported by Antonis Karydas - the RequestURI can be a non-sip
 * URI Jiang He - use address in route header. Significant changes to conform to
 * RFC 3261 made by Jeroen van Bemmel. Hagai Sela contributed a bug fix to the
 * strict route post processing code.
 *
 */

/**
 * This is the default router. When the implementation wants to forward a
 * request and had run out of othe options, then it calls this method to figure
 * out where to send the request. The default router implements a simple
 * "default routing algorithm" which just forwards to the configured proxy
 * address.
 *
 * 

* When android.javax.sip.USE_ROUTER_FOR_ALL_URIS is set to * false, the next hop is determined according to the following * algorithm: *

    *
  • If the request contains one or more Route headers, use the URI of the * topmost Route header as next hop, possibly modifying the request in the * process if the topmost Route header contains no lr parameter(*) *
  • Else, if the property android.javax.sip.OUTBOUND_PROXY is set, * use its value as the next hop *
  • Otherwise, use the request URI as next hop. If the request URI is not a * SIP URI, call {@link android.javax.sip.address.Router#getNextHop(Request)} provided * by the application. *
* *

* (*)Note that in case the topmost Route header contains no 'lr' parameter * (which means the next hop is a strict router), the implementation will * perform 'Route Information Postprocessing' as described in RFC3261 section * 16.6 step 6 (also known as "Route header popping"). That is, the following * modifications will be made to the request: *

    *
  1. The implementation places the Request-URI into the Route header field as * the last value. *
  2. The implementation then places the first Route header field value into * the Request-URI and removes that value from the Route header field. *
* Subsequently, the request URI will be used as next hop target * * * @version 1.2 $Revision: 1.20 $ $Date: 2010-12-02 22:04:12 $ * * @author M. Ranganathan
* */ public class DefaultRouter implements Router { private static StackLogger logger = CommonLogger.getLogger(DefaultRouter.class); private SIPTransactionStack sipStack; private Hop defaultRoute; private DefaultRouter() { } /** * Constructor. */ public DefaultRouter(SipStack sipStack, String defaultRoute) { this.sipStack = (SIPTransactionStack) sipStack; if (defaultRoute != null) { try { this.defaultRoute = (Hop) this.sipStack.getAddressResolver() .resolveAddress((Hop) (new HopImpl(defaultRoute))); } catch (IllegalArgumentException ex) { // The outbound proxy is optional. If specified it should be host:port/transport. logger .logError( "Invalid default route specification - need host:port/transport"); throw ex; } } } /** * Return addresses for default proxy to forward the request to. The list is * organized in the following priority. If the requestURI refers directly to * a host, the host and port information are extracted from it and made the * next hop on the list. If the default route has been specified, then it is * used to construct the next element of the list. * RouteHeader firstRoute = (RouteHeader) req.getHeader( RouteHeader.NAME ); * if (firstRoute!=null) { * URI uri = firstRoute.getAddress().getURI(); * if (uri.isSIPUri()) { * SipURI nextHop = (SipURI) uri; * if ( nextHop.hasLrParam() ) { * // OK, use it * } else { * nextHop = fixStrictRouting( req ); <--- Here, make the modifications as per RFC3261 * } * } else { * // error: non-SIP URI not allowed in Route headers * throw new SipException( "Request has Route header with non-SIP URI" ); * } * } else if (outboundProxy!=null) { * // use outbound proxy for nextHop * } else if ( req.getRequestURI().isSipURI() ) { * // use request URI for nextHop * } * * * * @param request * is the sip request to route. * */ public Hop getNextHop(Request request) throws SipException { SIPRequest sipRequest = (SIPRequest) request; RequestLine requestLine = sipRequest.getRequestLine(); if (requestLine == null) { return defaultRoute; } android.javax.sip.address.URI requestURI = requestLine.getUri(); if (requestURI == null) throw new IllegalArgumentException("Bad message: Null requestURI"); RouteList routes = sipRequest.getRouteHeaders(); /* * In case the topmost Route header contains no 'lr' parameter (which * means the next hop is a strict router), the implementation will * perform 'Route Information Postprocessing' as described in RFC3261 * section 16.6 step 6 (also known as "Route header popping"). That is, * the following modifications will be made to the request: * * The implementation places the Request-URI into the Route header field * as the last value. * * The implementation then places the first Route header field value * into the Request-URI and removes that value from the Route header * field. * * Subsequently, the request URI will be used as next hop target */ // In case of b2b UA and/or pure proxy behaviour, the routes list may not be null // but the only remaining entry might be removed via proxy in order to route the message to // its final destination. // We should make null check in order to avoid null pointer at line 201 if (routes != null && routes.getFirst () != null) { // to send the request through a specified hop the application is // supposed to prepend the appropriate Route header which. Route route = (Route) routes.getFirst(); URI uri = route.getAddress().getURI(); if (uri.isSipURI()) { SipURI sipUri = (SipURI) uri; if (!sipUri.hasLrParam()) { fixStrictRouting(sipRequest); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger .logDebug("Route post processing fixed strict routing"); } Hop hop = createHop(sipUri,request); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger .logDebug("NextHop based on Route:" + hop); return hop; } else { throw new SipException("First Route not a SIP URI"); } } else if (requestURI.isSipURI() && ((SipURI) requestURI).getMAddrParam() != null) { Hop hop = createHop((SipURI) requestURI,request); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger .logDebug("Using request URI maddr to route the request = " + hop.toString()); // JvB: don't remove it! // ((SipURI) requestURI).removeParameter("maddr"); return hop; } else if (defaultRoute != null) { if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger .logDebug("Using outbound proxy to route the request = " + defaultRoute.toString()); return defaultRoute; } else if (requestURI.isSipURI()) { Hop hop = createHop((SipURI) requestURI,request); if (hop != null && logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger.logDebug("Used request-URI for nextHop = " + hop.toString()); else if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger .logDebug("returning null hop -- loop detected"); } return hop; } else { // The internal router should never be consulted for non-sip URIs. InternalErrorHandler.handleException("Unexpected non-sip URI", this.logger); return null; } } /** * Performs strict router fix according to RFC3261 section 16.6 step 6 * * pre: top route header in request has no 'lr' parameter in URI post: * request-URI added as last route header, new req-URI = top-route-URI */ public void fixStrictRouting(SIPRequest req) { RouteList routes = req.getRouteHeaders(); Route first = (Route) routes.getFirst(); SipUri firstUri = (SipUri) first.getAddress().getURI(); routes.removeFirst(); // Add request-URI as last Route entry AddressImpl addr = new AddressImpl(); addr.setAddess(req.getRequestURI()); // don't clone it Route route = new Route(addr); routes.add(route); // as last one req.setRequestURI(firstUri); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug("post: fixStrictRouting" + req); } } /** * Utility method to create a hop from a SIP URI * * @param sipUri * @return */ protected final Hop createHop(SipURI sipUri, Request request) { // always use TLS when secure String transport = sipUri.isSecure() ? SIPConstants.TLS : sipUri .getTransportParam(); if (transport == null) { //@see issue 131 ViaHeader via = (ViaHeader) request.getHeader(ViaHeader.NAME); if(via != null) { transport = via.getTransport(); } if(transport == null) { transport = ListeningPoint.UDP; } } // sipUri.removeParameter("transport"); int port; if (sipUri.getPort() != -1) { port = sipUri.getPort(); } else { if (transport.equalsIgnoreCase(SIPConstants.TLS)) port = 5061; else port = 5060; // TCP or UDP } String host = sipUri.getMAddrParam() != null ? sipUri.getMAddrParam() : sipUri.getHost(); AddressResolver addressResolver = this.sipStack.getAddressResolver(); return addressResolver .resolveAddress(new HopImpl(host, port, transport)); } /** * Get the default hop. * * @return defaultRoute is the default route. public java.util.Iterator * getDefaultRoute(Request request) { return * this.getNextHops((SIPRequest)request); } */ public android.javax.sip.address.Hop getOutboundProxy() { return this.defaultRoute; } /* * (non-Javadoc) * * @see android.javax.sip.address.Router#getNextHop(android.javax.sip.message.Request) */ public ListIterator getNextHops(Request request) { try { LinkedList llist = new LinkedList(); llist.add(this.getNextHop(request)); return llist.listIterator(); } catch (SipException ex) { return null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy