1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/******************************************************************************* 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ******************************************************************************/ 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.stack; 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.*; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.*; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.*; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.*; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.*; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.net.AddressResolver; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.*; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Iterator; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.LinkedList; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.ListIterator; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.RouteHeader; 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ViaHeader; 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.*; 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.*; 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Bug reported by Will Scullin -- maddr was being ignored when routing 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * requests. Bug reported by Antonis Karydas - the RequestURI can be a non-sip 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * URI Jiang He - use address in route header. Significant changes to conform to 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3261 made by Jeroen van Bemmel. Hagai Sela contributed a bug fix to the 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * strict route post processing code. 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is the default router. When the implementation wants to forward a 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request and had run out of othe options, then it calls this method to figure 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * out where to send the request. The default router implements a simple 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * "default routing algorithm" which just forwards to the configured proxy 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * address. 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <p> 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * When <code>javax.sip.USE_ROUTER_FOR_ALL_URIS</code> is set to 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <code>false</code>, the next hop is determined according to the following 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * algorithm: 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <ul> 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li> If the request contains one or more Route headers, use the URI of the 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * topmost Route header as next hop, possibly modifying the request in the 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * process if the topmost Route header contains no lr parameter(*) 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li> Else, if the property <code>javax.sip.OUTBOUND_PROXY</code> is set, 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * use its value as the next hop 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li> Otherwise, use the request URI as next hop. If the request URI is not a 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * SIP URI, call {@link javax.sip.address.Router#getNextHop(Request)} provided 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * by the application. 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </ul> 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <p> 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (*)Note that in case the topmost Route header contains no 'lr' parameter 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (which means the next hop is a strict router), the implementation will 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * perform 'Route Information Postprocessing' as described in RFC3261 section 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 16.6 step 6 (also known as "Route header popping"). That is, the following 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * modifications will be made to the request: 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <ol> 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>The implementation places the Request-URI into the Route header field as 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the last value. 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>The implementation then places the first Route header field value into 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the Request-URI and removes that value from the Route header field. 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </ol> 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Subsequently, the request URI will be used as next hop target 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.17 $ $Date: 2009/11/14 20:06:17 $ 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class DefaultRouter implements Router { 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private SipStackImpl sipStack; 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Hop defaultRoute; 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private DefaultRouter() { 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor. 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public DefaultRouter(SipStack sipStack, String defaultRoute) { 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = (SipStackImpl) sipStack; 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (defaultRoute != null) { 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.defaultRoute = (Hop) this.sipStack.getAddressResolver() 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .resolveAddress((Hop) (new HopImpl(defaultRoute))); 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IllegalArgumentException ex) { 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The outbound proxy is optional. If specified it should be host:port/transport. 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPTransactionStack) sipStack) 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logError( 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Invalid default route specification - need host:port/transport"); 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return addresses for default proxy to forward the request to. The list is 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * organized in the following priority. If the requestURI refers directly to 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a host, the host and port information are extracted from it and made the 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * next hop on the list. If the default route has been specified, then it is 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * used to construct the next element of the list. <code> 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RouteHeader firstRoute = (RouteHeader) req.getHeader( RouteHeader.NAME ); 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if (firstRoute!=null) { 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * URI uri = firstRoute.getAddress().getURI(); 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if (uri.isSIPUri()) { 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * SipURI nextHop = (SipURI) uri; 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if ( nextHop.hasLrParam() ) { 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * // OK, use it 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * } else { 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * nextHop = fixStrictRouting( req ); <--- Here, make the modifications as per RFC3261 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * } 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * } else { 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * // error: non-SIP URI not allowed in Route headers 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * throw new SipException( "Request has Route header with non-SIP URI" ); 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * } 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * } else if (outboundProxy!=null) { 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * // use outbound proxy for nextHop 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * } else if ( req.getRequestURI().isSipURI() ) { 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * // use request URI for nextHop 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * } 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </code> 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param request 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the sip request to route. 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Hop getNextHop(Request request) throws SipException { 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest sipRequest = (SIPRequest) request; 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RequestLine requestLine = sipRequest.getRequestLine(); 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine == null) { 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return defaultRoute; 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang javax.sip.address.URI requestURI = requestLine.getUri(); 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestURI == null) 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("Bad message: Null requestURI"); 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RouteList routes = sipRequest.getRouteHeaders(); 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * In case the topmost Route header contains no 'lr' parameter (which 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * means the next hop is a strict router), the implementation will 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * perform 'Route Information Postprocessing' as described in RFC3261 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * section 16.6 step 6 (also known as "Route header popping"). That is, 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the following modifications will be made to the request: 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The implementation places the Request-URI into the Route header field 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * as the last value. 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The implementation then places the first Route header field value 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * into the Request-URI and removes that value from the Route header 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * field. 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Subsequently, the request URI will be used as next hop target 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (routes != null) { 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // to send the request through a specified hop the application is 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // supposed to prepend the appropriate Route header which. 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Route route = (Route) routes.getFirst(); 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang URI uri = route.getAddress().getURI(); 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (uri.isSipURI()) { 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipURI sipUri = (SipURI) uri; 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!sipUri.hasLrParam()) { 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang fixStrictRouting(sipRequest); 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug("Route post processing fixed strict routing"); 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Hop hop = createHop(sipUri,request); 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug("NextHop based on Route:" + hop); 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return hop; 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new SipException("First Route not a SIP URI"); 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (requestURI.isSipURI() 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && ((SipURI) requestURI).getMAddrParam() != null) { 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Hop hop = createHop((SipURI) requestURI,request); 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug("Using request URI maddr to route the request = " 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + hop.toString()); 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: don't remove it! 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // ((SipURI) requestURI).removeParameter("maddr"); 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return hop; 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (defaultRoute != null) { 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug("Using outbound proxy to route the request = " 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + defaultRoute.toString()); 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return defaultRoute; 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (requestURI.isSipURI()) { 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Hop hop = createHop((SipURI) requestURI,request); 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hop != null && sipStack.isLoggingEnabled()) 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Used request-URI for nextHop = " 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + hop.toString()); 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (sipStack.isLoggingEnabled()) { 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug("returning null hop -- loop detected"); 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return hop; 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The internal router should never be consulted for non-sip URIs. 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException("Unexpected non-sip URI", 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger()); 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Performs strict router fix according to RFC3261 section 16.6 step 6 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * pre: top route header in request has no 'lr' parameter in URI post: 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request-URI added as last route header, new req-URI = top-route-URI 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void fixStrictRouting(SIPRequest req) { 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RouteList routes = req.getRouteHeaders(); 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Route first = (Route) routes.getFirst(); 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipUri firstUri = (SipUri) first.getAddress().getURI(); 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang routes.removeFirst(); 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Add request-URI as last Route entry 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang AddressImpl addr = new AddressImpl(); 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang addr.setAddess(req.getRequestURI()); // don't clone it 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Route route = new Route(addr); 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang routes.add(route); // as last one 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang req.setRequestURI(firstUri); 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("post: fixStrictRouting" + req); 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Utility method to create a hop from a SIP URI 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipUri 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private final Hop createHop(SipURI sipUri, Request request) { 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // always use TLS when secure 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String transport = sipUri.isSecure() ? SIPConstants.TLS : sipUri 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getTransportParam(); 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transport == null) { 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //@see issue 131 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ViaHeader via = (ViaHeader) request.getHeader(ViaHeader.NAME); 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transport = via.getTransport(); 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sipUri.removeParameter("transport"); 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int port; 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipUri.getPort() != -1) { 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang port = sipUri.getPort(); 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transport.equalsIgnoreCase(SIPConstants.TLS)) 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang port = 5061; 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang port = 5060; // TCP or UDP 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String host = sipUri.getMAddrParam() != null ? sipUri.getMAddrParam() 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang : sipUri.getHost(); 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang AddressResolver addressResolver = this.sipStack.getAddressResolver(); 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return addressResolver 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .resolveAddress(new HopImpl(host, port, transport)); 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the default hop. 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return defaultRoute is the default route. public java.util.Iterator 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * getDefaultRoute(Request request) { return 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * this.getNextHops((SIPRequest)request); } 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public javax.sip.address.Hop getOutboundProxy() { 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.defaultRoute; 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see javax.sip.address.Router#getNextHop(javax.sip.message.Request) 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ListIterator getNextHops(Request request) { 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang LinkedList llist = new LinkedList(); 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang llist.add(this.getNextHop(request)); 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return llist.listIterator(); 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SipException ex) { 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 346