package org.mobicents.mgcp.stack; import jain.protocol.ip.mgcp.JainMgcpCommandEvent; import jain.protocol.ip.mgcp.JainMgcpResponseEvent; import jain.protocol.ip.mgcp.message.AuditConnection; import jain.protocol.ip.mgcp.message.AuditConnectionResponse; import jain.protocol.ip.mgcp.message.parms.CallIdentifier; import jain.protocol.ip.mgcp.message.parms.ConnectionDescriptor; import jain.protocol.ip.mgcp.message.parms.ConnectionIdentifier; import jain.protocol.ip.mgcp.message.parms.ConnectionMode; import jain.protocol.ip.mgcp.message.parms.ConnectionParm; import jain.protocol.ip.mgcp.message.parms.InfoCode; import jain.protocol.ip.mgcp.message.parms.LocalOptionValue; import jain.protocol.ip.mgcp.message.parms.NotifiedEntity; import jain.protocol.ip.mgcp.message.parms.ReturnCode; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.net.InetAddress; import java.text.ParseException; import org.apache.log4j.Logger; import org.mobicents.mgcp.stack.parser.MgcpContentHandler; import org.mobicents.mgcp.stack.parser.MgcpMessageParser; import org.mobicents.mgcp.stack.parser.Utils; /** * * @author amit bhayani * */ public class AuditConnectionHandler extends TransactionHandler { private static final Logger logger = Logger.getLogger(AuditConnectionHandler.class); private AuditConnection command; private AuditConnectionResponse response; private ConnectionIdentifier connectionIdentifier = null; private InfoCode[] requestedInfo = null; boolean RCfirst = false; public AuditConnectionHandler(JainMgcpStackImpl stack) { super(stack); } public AuditConnectionHandler(JainMgcpStackImpl stack, InetAddress address, int port) { super(stack, address, port); } @Override public JainMgcpCommandEvent decodeCommand(String message) throws ParseException { Utils utils = utilsFactory.allocate(); MgcpMessageParser parser = new MgcpMessageParser(new CommandContentHandle(utils)); try { parser.parse(message); command = new AuditConnection(source != null ? source : stack, endpoint, connectionIdentifier, requestedInfo); command.setTransactionHandle(remoteTID); } catch (Exception e) { throw new ParseException(e.getMessage(), -1); } finally { utilsFactory.deallocate(utils); } return command; } @Override public JainMgcpResponseEvent decodeResponse(String message) throws ParseException { Utils utils = utilsFactory.allocate(); MgcpMessageParser parser = new MgcpMessageParser(new ResponseContentHandle(utils)); try { parser.parse(message); } catch (IOException e) { logger.error("Parsing of AUCX Response failed ", e); } finally { utilsFactory.deallocate(utils); } return response; } @Override public String encode(JainMgcpCommandEvent event) { // encode message header Utils utils = utilsFactory.allocate(); AuditConnection evt = (AuditConnection) event; StringBuffer s = new StringBuffer(); s.append("AUCX ").append(evt.getTransactionHandle()).append(TransactionHandler.SINGLE_CHAR_SPACE).append( evt.getEndpointIdentifier()).append(MGCP_VERSION).append(NEW_LINE); // encode mandatory parameters if (evt.getConnectionIdentifier() != null) { s.append("I:").append(evt.getConnectionIdentifier()).append(NEW_LINE); } InfoCode[] requestedInfos = evt.getRequestedInfo(); if (requestedInfos != null) { s.append("F: ").append(utils.encodeInfoCodeList(requestedInfos)); int foundRC = 0; int foundLC = 0; // This is to determine which SDP is RemoteSDP and which one is // LocalSDP for (int count = 0; count < requestedInfos.length; count++) { InfoCode info = requestedInfos[count]; switch (info.getInfoCode()) { case (InfoCode.REMOTE_CONNECTION_DESCRIPTOR): foundRC = count; if (foundLC != 0 && foundLC < count) { RCfirst = false; } else { RCfirst = true; } break; case (InfoCode.LOCAL_CONNECTION_DESCRIPTOR): foundLC = count; if (foundRC != 0 && foundRC < count) { RCfirst = true; } else { RCfirst = false; } break; } } } utilsFactory.deallocate(utils); // return msg; return s.toString(); } @Override public String encode(JainMgcpResponseEvent event) { Utils utils = utilsFactory.allocate(); AuditConnectionResponse response = (AuditConnectionResponse) event; ReturnCode returnCode = response.getReturnCode(); StringBuffer s = new StringBuffer(); s.append(returnCode.getValue()).append(SINGLE_CHAR_SPACE).append(response.getTransactionHandle()).append( SINGLE_CHAR_SPACE).append(returnCode.getComment()).append(NEW_LINE); if (response.getCallIdentifier() != null) { s.append("C:").append(response.getCallIdentifier()).append(NEW_LINE); } if (response.getNotifiedEntity() != null) { s.append("N:").append(utils.encodeNotifiedEntity(response.getNotifiedEntity())).append(NEW_LINE); } if (response.getLocalConnectionOptions() != null) { s.append("L:").append(utils.encodeLocalOptionValueList(response.getLocalConnectionOptions())).append( NEW_LINE); } if (response.getMode() != null) { s.append("M:").append(response.getMode()).append(NEW_LINE); } if (response.getConnectionParms() != null) { s.append("P:").append(utils.encodeConnectionParms(response.getConnectionParms())).append(NEW_LINE); } if (RCfirst && response.getRemoteConnectionDescriptor() != null) { s.append(NEW_LINE).append(response.getRemoteConnectionDescriptor()).append(NEW_LINE); } if (response.getLocalConnectionDescriptor() != null) { s.append(NEW_LINE).append(response.getLocalConnectionDescriptor()).append(NEW_LINE); } if (!RCfirst && response.getRemoteConnectionDescriptor() != null) { s.append(NEW_LINE).append(response.getRemoteConnectionDescriptor()).append(NEW_LINE); } utilsFactory.deallocate(utils); return s.toString(); // return msg; } @Override public JainMgcpResponseEvent getProvisionalResponse() { AuditConnectionResponse provisionalResponse = null; if (!sent) { provisionalResponse = new AuditConnectionResponse(source != null ? source : stack, ReturnCode.Transaction_Being_Executed); provisionalResponse.setTransactionHandle(remoteTID); } return provisionalResponse; } private class CommandContentHandle implements MgcpContentHandler { Utils utils = null; public CommandContentHandle(Utils utils) { this.utils = utils; } /** * Receive notification of the header of a message. Parser will call * this method to report about header reading. * * @param header * the header from the message. */ public void header(String header) throws ParseException { // Can't create the AuditConnection object here as // ConnectionIdentifier and InfoCode[] is required } /** * Receive notification of the parameter of a message. Parser will call * this method to report about parameter reading. * * @param name * the name of the parameter * @param value * the value of the parameter. */ public void param(String name, String value) throws ParseException { if (name.equalsIgnoreCase("I")) { connectionIdentifier = new ConnectionIdentifier(value); } else if (name.equalsIgnoreCase("F")) { int RCindex = value.indexOf("RC"); int LCindex = value.indexOf("LC"); if (RCindex != -1 && RCindex < LCindex) { RCfirst = true; } requestedInfo = utils.decodeInfoCodeList(value); } else { logger.error("Unknown code while encoding AUCX Command name = " + name + " value = " + value); } } /** * Receive notification of the session description. Parser will call * this method to report about session descriptor reading. * * @param sd * the session description from message. */ public void sessionDescription(String sd) throws ParseException { throw new ParseException("SessionDescription shouldn't have been included in AUCX command", 0); } } private class ResponseContentHandle implements MgcpContentHandler { Utils utils = null; public ResponseContentHandle(Utils utils) { this.utils = utils; } /** * Receive notification of the header of a message. Parser will call * this method to report about header reading. * * @param header * the header from the message. */ public void header(String header) throws ParseException { String[] tokens = utils.splitStringBySpace(header); int tid = Integer.parseInt(tokens[1]); response = new AuditConnectionResponse(source != null ? source : stack, utils.decodeReturnCode(Integer .parseInt(tokens[0]))); response.setTransactionHandle(tid); } /** * Receive notification of the parameter of a message. Parser will call * this method to report about parameter reading. * * @param name * the name of the paremeter * @param value * the value of the parameter. */ public void param(String name, String value) throws ParseException { if (name.equalsIgnoreCase("C")) { response.setCallIdentifier(new CallIdentifier(value)); } else if (name.equalsIgnoreCase("N")) { NotifiedEntity n = utils.decodeNotifiedEntity(value, true); response.setNotifiedEntity(n); } else if (name.equalsIgnoreCase("L")) { LocalOptionValue[] LocalOptionValueList = utils.decodeLocalOptionValueList(value); response.setLocalConnectionOptions(LocalOptionValueList); } else if (name.equalsIgnoreCase("M")) { ConnectionMode connectionMode = utils.decodeConnectionMode(value); response.setMode(connectionMode); } else if (name.equalsIgnoreCase("P")) { ConnectionParm[] connectionParms = utils.decodeConnectionParms(value); response.setConnectionParms(connectionParms); } else { logger.warn("Unidentified AUCX Response parameter " + name + " with value = " + value); } } /** * Receive notification of the session description. Parser will call * this method to report about session descriptor reading. * * @param sd * the session description from message. */ public void sessionDescription(String sd) throws ParseException { StringReader stringReader = new StringReader(sd); BufferedReader reader = new BufferedReader(stringReader); String line = null; boolean sdpPresent = false; String sdp1 = ""; String sdp2 = ""; try { while ((line = reader.readLine()) != null) { line = line.trim(); sdpPresent = line.length() == 0; if (sdpPresent) break; sdp1 = sdp1 + line.trim() + "\r\n"; } while ((line = reader.readLine()) != null) { line = line.trim(); sdp2 = sdp2 + line.trim() + "\r\n"; } } catch (IOException e) { logger.error("Error while reading the SDP for AUCX Response and decoding to AUCX command ", e); } if (RCfirst) { response.setRemoteConnectionDescriptor(new ConnectionDescriptor(sdp1)); if (!sdp2.equals("")) { response.setLocalConnectionDescriptor(new ConnectionDescriptor(sdp2)); } } else { response.setLocalConnectionDescriptor(new ConnectionDescriptor(sdp1)); if (!sdp2.equals("")) { response.setRemoteConnectionDescriptor(new ConnectionDescriptor(sdp2)); } } } } }