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