/protocols/jain-mgcp/stack/src/main/java/org/mobicents/protocols/mgcp/stack/MessageHandler.java

http://mobicents.googlecode.com/ · Java · 257 lines · 138 code · 37 blank · 82 comment · 40 complexity · 524dad61fc85676efca617bd8385845f MD5 · raw file

  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. /*
  23. * File Name : MessageHandler.java
  24. *
  25. * The JAIN MGCP API implementaion.
  26. *
  27. * The source code contained in this file is in in the public domain.
  28. * It can be used in any project or product without prior permission,
  29. * license or royalty payments. There is NO WARRANTY OF ANY KIND,
  30. * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION,
  31. * THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
  32. * AND DATA ACCURACY. We do not warrant or make any representations
  33. * regarding the use of the software or the results thereof, including
  34. * but not limited to the correctness, accuracy, reliability or
  35. * usefulness of the software.
  36. */
  37. package org.mobicents.protocols.mgcp.stack;
  38. import jain.protocol.ip.mgcp.message.parms.EndpointIdentifier;
  39. import java.io.UnsupportedEncodingException;
  40. import java.net.InetAddress;
  41. import java.util.ArrayList;
  42. import org.apache.log4j.Logger;
  43. import org.mobicents.protocols.mgcp.parser.Utils;
  44. import org.mobicents.protocols.mgcp.utils.PacketRepresentation;
  45. /**
  46. *
  47. * @author Oleg Kulikov
  48. */
  49. public class MessageHandler {
  50. private JainMgcpStackImpl stack;
  51. private static Logger logger = Logger.getLogger(MessageHandler.class);
  52. private Utils utils = null;
  53. private static ArrayList<String> mList = new ArrayList<String>();
  54. /** Creates a new instance of MessageHandler */
  55. public MessageHandler(JainMgcpStackImpl jainMgcpStackImpl) {
  56. this.stack = jainMgcpStackImpl;
  57. utils = jainMgcpStackImpl.getUtilsFactory().allocate();
  58. }
  59. /**
  60. * RFC 3435, $3.5.5: split piggy backed messages again
  61. * <P>
  62. * Messages within the packet are split on their separator "EOL DOT EOL".
  63. *
  64. * @param packet
  65. * the packet to split
  66. * @return array of all separate messages
  67. */
  68. public static String[] piggyDismount(byte[] msgBuffer, int length) {
  69. try {
  70. int msgStart = 0;
  71. int msgLength = 0;
  72. String currentLine = null;
  73. for (int i = 0; i < length - 1; i++) {
  74. if ((msgBuffer[i] == '\n' || msgBuffer[i] == '\r') && msgBuffer[i + 1] == '.') {
  75. msgLength = i - msgStart;
  76. try {
  77. currentLine = new String(msgBuffer, msgStart, msgLength + 1, "UTF-8");
  78. mList.add(currentLine);
  79. } catch (UnsupportedEncodingException e) {
  80. logger.error(e);
  81. }
  82. i = i + 3;
  83. msgStart = i;
  84. }
  85. }
  86. try {
  87. msgLength = length - msgStart;
  88. currentLine = new String(msgBuffer, msgStart, msgLength, "UTF-8");
  89. mList.add(currentLine);
  90. } catch (UnsupportedEncodingException e) {
  91. logger.error(e); // Should never happen though
  92. }
  93. String[] result = new String[mList.size()];
  94. return (String[]) mList.toArray(result);
  95. } finally {
  96. mList.clear();
  97. }
  98. }
  99. public boolean isRequest(String header) {
  100. header = header.trim();
  101. char ch = header.charAt(0);
  102. if (Character.isDigit(ch)) {
  103. return false;
  104. }
  105. return true;
  106. // Dont use matcher due to bug
  107. // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6337993
  108. // Matcher m = p.matcher(header);
  109. // return m.matches();
  110. // return header.matches("[\\w]{4}(\\s|\\S)*");
  111. }
  112. public void scheduleMessages(PacketRepresentation pr) {
  113. try {
  114. final InetAddress address = pr.getRemoteAddress();
  115. final int port = pr.getRemotePort();
  116. for (String msg : piggyDismount(pr.getRawData(), pr.getLength())) {
  117. int pos = msg.indexOf("\n");
  118. // extract message header to determine transaction handle
  119. // parameter and type of the received message
  120. String header = msg.substring(0, pos).trim();
  121. if (logger.isDebugEnabled()) {
  122. logger.debug("Message header: " + header);
  123. }
  124. // check message type if this message is command then create new
  125. // transaction handler for specified type of this message. if
  126. // received message is a response then try to find corresponded
  127. // transaction to handle this message
  128. String tokens[] = utils.splitStringBySpace(header);
  129. if (isRequest(header)) {
  130. final String verb = tokens[0];
  131. final String remoteTxIdString = tokens[1];
  132. final EndpointIdentifier endpoint = utils.decodeEndpointIdentifier(tokens[2].trim());
  133. if (logger.isDebugEnabled()) {
  134. logger.debug("Processing command message = " + verb + " remote Tx = " + remoteTxIdString);
  135. }
  136. Integer remoteTxIdIntegere = new Integer(remoteTxIdString);
  137. // Check if the Response still in responseTx Map
  138. TransactionHandler completedTxHandler = stack.getCompletedTransactions().get(remoteTxIdIntegere);
  139. if (completedTxHandler != null) {
  140. // EndpointHandler eh = completedTxHandler.getEndpointHandler();
  141. completedTxHandler.markRetransmision();
  142. completedTxHandler.run();
  143. // eh.scheduleTransactionHandler(completedTxHandler);
  144. if (logger.isDebugEnabled()) {
  145. logger.debug("Received Command for which stack has already sent response Tx = " + verb
  146. + " " + remoteTxIdIntegere);
  147. }
  148. return;
  149. }
  150. Integer tmpLoaclTID = stack.getRemoteTxToLocalTxMap().get(remoteTxIdIntegere);
  151. if (tmpLoaclTID != null) {
  152. TransactionHandler ongoingTxHandler = stack.getLocalTransactions().get(tmpLoaclTID);
  153. ongoingTxHandler.sendProvisionalResponse();
  154. if (logger.isDebugEnabled()) {
  155. logger.debug("Received Command for ongoing Tx = " + remoteTxIdIntegere);
  156. }
  157. return;
  158. }
  159. // If we are here, it means this is new TX, we have to
  160. // create TxH and EH
  161. TransactionHandler handler;
  162. if (verb.equalsIgnoreCase("crcx")) {
  163. handler = new CreateConnectionHandler(stack, address, port);
  164. } else if (verb.equalsIgnoreCase("mdcx")) {
  165. handler = new ModifyConnectionHandler(stack, address, port);
  166. } else if (verb.equalsIgnoreCase("dlcx")) {
  167. handler = new DeleteConnectionHandler(stack, address, port);
  168. } else if (verb.equalsIgnoreCase("epcf")) {
  169. handler = new EndpointConfigurationHandler(stack, address, port);
  170. } else if (verb.equalsIgnoreCase("rqnt")) {
  171. handler = new NotificationRequestHandler(stack, address, port);
  172. } else if (verb.equalsIgnoreCase("ntfy")) {
  173. handler = new NotifyHandler(stack, address, port);
  174. } else if (verb.equalsIgnoreCase("rsip")) {
  175. handler = new RestartInProgressHandler(stack, address, port);
  176. } else if (verb.equalsIgnoreCase("auep")) {
  177. handler = new AuditEndpointHandler(stack, address, port);
  178. } else if (verb.equalsIgnoreCase("aucx")) {
  179. handler = new AuditConnectionHandler(stack, address, port);
  180. } else {
  181. logger.warn("Unsupported message verbose " + verb);
  182. return;
  183. }
  184. // This makes this command to be set in queue to process
  185. handler.receiveRequest(endpoint, msg, remoteTxIdIntegere);
  186. // boolean useFakeOnWildcard = false;
  187. // if (handler instanceof CreateConnectionHandler) {
  188. // useFakeOnWildcard = EndpointHandler.isAnyOfWildcard(handler.getEndpointId());
  189. // }
  190. // EndpointHandler eh = stack.getEndpointHandler(handler.getEndpointId(), useFakeOnWildcard);
  191. // eh.addTransactionHandler(handler);
  192. //
  193. // eh.scheduleTransactionHandler(handler);
  194. // handle.receiveCommand(msg);
  195. } else {
  196. // RESPONSE HANDLING
  197. if (logger.isDebugEnabled()) {
  198. logger.debug("Processing response message");
  199. }
  200. // String domainName = address.getHostName();
  201. String tid = tokens[1];
  202. // XXX:TransactionHandler handler = (TransactionHandler)
  203. // stack.getLocalTransaction(Integer.valueOf(tid));
  204. TransactionHandler handler = (TransactionHandler) stack.getLocalTransactions().get(
  205. Integer.valueOf(tid));
  206. if (handler == null) {
  207. logger.warn("--- Address:" + address + "\nPort:" + port + "\nID:" + this.hashCode()
  208. + "\n Unknown transaction: " + tid);
  209. return;
  210. }
  211. handler.receiveResponse(msg);
  212. // EndpointHandler eh = handler.getEndpointHandler();
  213. // eh.scheduleTransactionHandler(handler);
  214. }
  215. }
  216. } finally {
  217. pr.release();
  218. }
  219. }
  220. }