PageRenderTime 30ms CodeModel.GetById 17ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/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/*
 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}