PageRenderTime 167ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/core/dispatchers/RequestDispatcher.java

http://mobicents.googlecode.com/
Java | 285 lines | 178 code | 17 blank | 90 comment | 42 complexity | bc16969f3d9c776f82b12b48a4572f60 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.mobicents.servlet.sip.core.dispatchers;
  23. import gov.nist.javax.sip.TransactionExt;
  24. import gov.nist.javax.sip.message.MessageExt;
  25. import java.text.ParseException;
  26. import javax.servlet.sip.ar.SipRouteModifier;
  27. import javax.sip.ClientTransaction;
  28. import javax.sip.Dialog;
  29. import javax.sip.InvalidArgumentException;
  30. import javax.sip.ServerTransaction;
  31. import javax.sip.SipException;
  32. import javax.sip.SipProvider;
  33. import javax.sip.Transaction;
  34. import javax.sip.TransactionUnavailableException;
  35. import javax.sip.header.ContentTypeHeader;
  36. import javax.sip.header.MaxForwardsHeader;
  37. import javax.sip.header.ViaHeader;
  38. import javax.sip.message.Request;
  39. import javax.sip.message.Response;
  40. import org.apache.log4j.Logger;
  41. import org.mobicents.servlet.sip.JainSipUtils;
  42. import org.mobicents.servlet.sip.core.MobicentsExtendedListeningPoint;
  43. import org.mobicents.servlet.sip.core.SipNetworkInterfaceManager;
  44. import org.mobicents.servlet.sip.core.SipSessionRoutingType;
  45. import org.mobicents.servlet.sip.core.session.MobicentsSipSession;
  46. import org.mobicents.servlet.sip.message.SipFactoryImpl;
  47. import org.mobicents.servlet.sip.message.SipServletRequestImpl;
  48. import org.mobicents.servlet.sip.message.TransactionApplicationData;
  49. /**
  50. * @author <A HREF="mailto:jean.deruelle@gmail.com">Jean Deruelle</A>
  51. *
  52. */
  53. public abstract class RequestDispatcher extends MessageDispatcher {
  54. private static final Logger logger = Logger.getLogger(RequestDispatcher.class);
  55. public RequestDispatcher() {}
  56. // public RequestDispatcher(SipApplicationDispatcher sipApplicationDispatcher) {
  57. // super(sipApplicationDispatcher);
  58. // }
  59. /**
  60. * Forward statefully a request whether it is initial or subsequent
  61. * and keep track of the transactions used in application data of each transaction
  62. * @param sipServletRequest the sip servlet request to forward statefully
  63. * @param sipRouteModifier the route modifier returned by the AR when receiving the request
  64. * @throws ParseException
  65. * @throws TransactionUnavailableException
  66. * @throws SipException
  67. * @throws InvalidArgumentException
  68. */
  69. protected final void forwardRequestStatefully(SipServletRequestImpl sipServletRequest, SipSessionRoutingType sipSessionRoutingType, SipRouteModifier sipRouteModifier) throws Exception {
  70. final SipNetworkInterfaceManager sipNetworkInterfaceManager = sipApplicationDispatcher.getSipNetworkInterfaceManager();
  71. Request clonedRequest = (Request)sipServletRequest.getMessage().clone();
  72. //Add via header
  73. String transport = JainSipUtils.findTransport(clonedRequest);
  74. ((MessageExt)clonedRequest).setApplicationData(null);
  75. MobicentsSipSession session = sipServletRequest.getSipSession();
  76. String outboundInterface = null;
  77. if(session != null) {
  78. outboundInterface = session.getOutboundInterface();
  79. }
  80. ViaHeader viaHeader = JainSipUtils.createViaHeader(
  81. sipNetworkInterfaceManager, clonedRequest, null, outboundInterface);
  82. // used for response routing, stored later in the tx app data so that it interoperates with UA/proxies not handling correctly via params
  83. String appNotDeployed = null;
  84. boolean noAppReturned = false;
  85. String modifier = null;
  86. if(session != null) {
  87. if(SipSessionRoutingType.CURRENT_SESSION.equals(sipSessionRoutingType)) {
  88. //an app was found or an app was returned by the AR but not found
  89. String handlerName = session.getHandler();
  90. if(handlerName != null) {
  91. final String branch = JainSipUtils.createBranch(session.getSipApplicationSession().getKey().getId(), sipApplicationDispatcher.getHashFromApplicationName(session.getKey().getApplicationName()));
  92. viaHeader.setBranch(branch);
  93. } else {
  94. // if the handler name is null it means that the app returned by the AR was not deployed
  95. // and couldn't be called,
  96. // we specify it so that on response handling this app can be skipped
  97. final String branch = JainSipUtils.createBranch(session.getSipApplicationSession().getKey().getId(), sipApplicationDispatcher.getHashFromApplicationName(session.getKey().getApplicationName()));
  98. viaHeader.setBranch(branch);
  99. appNotDeployed = session.getKey().getApplicationName();
  100. }
  101. clonedRequest.addHeader(viaHeader);
  102. } else {
  103. if(SipRouteModifier.NO_ROUTE.equals(sipRouteModifier)) {
  104. // no app was returned by the AR
  105. noAppReturned = true;
  106. } else {
  107. modifier = sipRouteModifier.toString();
  108. }
  109. clonedRequest.addHeader(viaHeader);
  110. }
  111. } else {
  112. if(SipRouteModifier.NO_ROUTE.equals(sipRouteModifier)) {
  113. // no app was returned by the AR and no application was selected before
  114. // if the handler name is null it means that the app returned by the AR was not deployed
  115. // and couldn't be called,
  116. // we specify it so that on response handling this app can be skipped
  117. noAppReturned = true;
  118. } else {
  119. modifier = sipRouteModifier.toString();
  120. }
  121. clonedRequest.addHeader(viaHeader);
  122. }
  123. MobicentsExtendedListeningPoint extendedListeningPoint =
  124. sipNetworkInterfaceManager.findMatchingListeningPoint(transport, false);
  125. if(logger.isDebugEnabled()) {
  126. logger.debug("Matching listening point found "
  127. + extendedListeningPoint);
  128. }
  129. SipProvider sipProvider = extendedListeningPoint.getSipProvider();
  130. ServerTransaction serverTransaction = (ServerTransaction) sipServletRequest.getTransaction();
  131. Dialog dialog = sipServletRequest.getDialog();
  132. //decrease the Max Forward Header
  133. MaxForwardsHeader maxForwardsHeader = (MaxForwardsHeader) clonedRequest
  134. .getHeader(MaxForwardsHeader.NAME);
  135. if (maxForwardsHeader == null) {
  136. maxForwardsHeader = SipFactoryImpl.headerFactory.createMaxForwardsHeader(JainSipUtils.MAX_FORWARD_HEADER_VALUE);
  137. clonedRequest.addHeader(maxForwardsHeader);
  138. } else {
  139. if(maxForwardsHeader.getMaxForwards() - 1 > 0) {
  140. maxForwardsHeader.setMaxForwards(maxForwardsHeader.getMaxForwards() - 1);
  141. } else {
  142. //Max forward header equals to 0, thus sending too many hops response
  143. sendErrorResponse(Response.TOO_MANY_HOPS, sipServletRequest, sipProvider);
  144. return;
  145. }
  146. }
  147. if(logger.isDebugEnabled()) {
  148. if(SipRouteModifier.NO_ROUTE.equals(sipRouteModifier)) {
  149. logger.debug("Routing Back to the container the following request "
  150. + clonedRequest);
  151. } else {
  152. logger.debug("Routing externally the following request "
  153. + clonedRequest);
  154. }
  155. }
  156. if(logger.isDebugEnabled()) {
  157. logger.debug("Dialog existing " + (dialog != null));
  158. }
  159. if(dialog == null) {
  160. Transaction transaction = ((TransactionApplicationData)
  161. serverTransaction.getApplicationData()).getSipServletMessage().getTransaction();
  162. if(transaction == null || transaction instanceof ServerTransaction) {
  163. ClientTransaction ctx = sipProvider.getNewClientTransaction(clonedRequest);
  164. JainSipUtils.setTransactionTimers((TransactionExt) ctx, sipApplicationDispatcher);
  165. //keeping the server transaction in the client transaction's application data
  166. TransactionApplicationData appData = new TransactionApplicationData(sipServletRequest);
  167. appData.setTransaction(serverTransaction);
  168. appData.setNoAppReturned(noAppReturned);
  169. appData.setAppNotDeployed(appNotDeployed);
  170. appData.setModifier(modifier);
  171. ctx.setApplicationData(appData);
  172. //keeping the client transaction in the server transaction's application data
  173. ((TransactionApplicationData)serverTransaction.getApplicationData()).setTransaction(ctx);
  174. if(logger.isInfoEnabled()) {
  175. logger.info("Sending the request through a new client transaction " + clonedRequest);
  176. }
  177. try {
  178. ctx.sendRequest();
  179. } catch(SipException e) {
  180. JainSipUtils.terminateTransaction(ctx);
  181. throw e;
  182. }
  183. } else {
  184. TransactionApplicationData appData = (TransactionApplicationData) transaction.getApplicationData();
  185. if(appData == null) {
  186. appData = new TransactionApplicationData(sipServletRequest);
  187. appData.setTransaction(transaction);
  188. }
  189. appData.setNoAppReturned(noAppReturned);
  190. appData.setAppNotDeployed(appNotDeployed);
  191. appData.setModifier(modifier);
  192. //keeping the client transaction in the server transaction's application data
  193. ((TransactionApplicationData)serverTransaction.getApplicationData()).setTransaction(transaction);
  194. if(logger.isInfoEnabled()) {
  195. logger.info("Sending the request through the existing transaction " + clonedRequest);
  196. }
  197. ((ClientTransaction)transaction).sendRequest();
  198. }
  199. } else if ( clonedRequest.getMethod().equals("ACK") ) {
  200. if(logger.isInfoEnabled()) {
  201. logger.info("Sending the ACK through the dialog " + clonedRequest);
  202. }
  203. dialog.sendAck(clonedRequest);
  204. } else {
  205. Request dialogRequest=
  206. dialog.createRequest(clonedRequest.getMethod());
  207. Object content=clonedRequest.getContent();
  208. if (content!=null) {
  209. ContentTypeHeader contentTypeHeader= (ContentTypeHeader)
  210. clonedRequest.getHeader(ContentTypeHeader.NAME);
  211. if (contentTypeHeader!=null) {
  212. dialogRequest.setContent(content,contentTypeHeader);
  213. }
  214. }
  215. // Copy all the headers from the original request to the
  216. // dialog created request:
  217. // => not needed already done by the clone method
  218. // ListIterator<String> headerNamesListIterator=clonedRequest.getHeaderNames();
  219. // while (headerNamesListIterator.hasNext()) {
  220. // String name=headerNamesListIterator.next();
  221. // Header header=dialogRequest.getHeader(name);
  222. // if (header==null ) {
  223. // ListIterator<Header> li=clonedRequest.getHeaders(name);
  224. // if (li!=null) {
  225. // while (li.hasNext() ) {
  226. // Header h = li.next();
  227. // dialogRequest.addHeader(h);
  228. // }
  229. // }
  230. // }
  231. // else {
  232. // if ( header instanceof ViaHeader) {
  233. // ListIterator<Header> li= clonedRequest.getHeaders(name);
  234. // if (li!=null) {
  235. // dialogRequest.removeHeader(name);
  236. // Vector v=new Vector();
  237. // while (li.hasNext() ) {
  238. // Header h=li.next();
  239. // v.addElement(h);
  240. // }
  241. // for (int k=(v.size()-1);k>=0;k--) {
  242. // Header h=(Header)v.elementAt(k);
  243. // dialogRequest.addHeader(h);
  244. // }
  245. // }
  246. // }
  247. // }
  248. // }
  249. ClientTransaction clientTransaction =
  250. sipProvider.getNewClientTransaction(dialogRequest);
  251. JainSipUtils.setTransactionTimers((TransactionExt) clientTransaction, sipApplicationDispatcher);
  252. //keeping the server transaction in the client transaction's application data
  253. TransactionApplicationData appData = new TransactionApplicationData(sipServletRequest);
  254. appData.setNoAppReturned(noAppReturned);
  255. appData.setAppNotDeployed(appNotDeployed);
  256. appData.setModifier(modifier);
  257. appData.setTransaction(serverTransaction);
  258. clientTransaction.setApplicationData(appData);
  259. //keeping the client transaction in the server transaction's application data
  260. ((TransactionApplicationData)serverTransaction.getApplicationData()).setTransaction(clientTransaction);
  261. dialog.setApplicationData(appData);
  262. if(logger.isInfoEnabled()) {
  263. logger.info("Sending the request through the dialog " + clonedRequest);
  264. }
  265. dialog.sendRequest(clientTransaction);
  266. }
  267. }
  268. }