/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.restcomm.media.control.mgcp.tx.cmd; import java.io.IOException; import org.restcomm.media.control.mgcp.MgcpEvent; import org.restcomm.media.control.mgcp.controller.MgcpCall; import org.restcomm.media.control.mgcp.controller.MgcpConnection; import org.restcomm.media.control.mgcp.controller.MgcpEndpoint; import org.restcomm.media.control.mgcp.controller.naming.UnknownEndpointException; import org.restcomm.media.control.mgcp.message.MgcpRequest; import org.restcomm.media.control.mgcp.message.MgcpResponse; import org.restcomm.media.control.mgcp.message.MgcpResponseCode; import org.restcomm.media.control.mgcp.message.Parameter; import org.restcomm.media.control.mgcp.tx.Action; import org.restcomm.media.scheduler.PriorityQueueScheduler; import org.restcomm.media.scheduler.Scheduler; import org.restcomm.media.scheduler.Task; import org.restcomm.media.scheduler.TaskChain; import org.restcomm.media.spi.utils.Text; import org.apache.log4j.Logger; /** * Modify connection command. * * @author Oifa Yulian */ public class DeleteConnectionCmd extends Action { // response strings private final static Text CALLID_MISSING = new Text( "Missing call identifier"); private final static Text UNKNOWN_CALL_IDENTIFIER = new Text( "Could not find this call with specified identifier"); private final static Text CONNECTIONID_EXPECTED = new Text( "Connection identifier was not specified"); private final static Text SUCCESS = new Text("Success"); private MgcpRequest request; private Parameter connectionID; // local and domain name parts of the endpoint identifier private Text localName = new Text(); private Text domainName = new Text(); // layout local and domain names into endpoint identifier private Text[] endpointName = new Text[] { localName, domainName }; private MgcpEndpoint endpoint; private MgcpEndpoint[] endpoints = new MgcpEndpoint[1]; private TaskChain handler; // error code and message private int code; private Text message; private int tx, rx; private final static Logger logger = Logger.getLogger(DeleteConnectionCmd.class); public DeleteConnectionCmd(Scheduler scheduler) { handler = new TaskChain(2, scheduler); Delete delete = new Delete(); Responder responder = new Responder(); handler.add(delete); handler.add(responder); ErrorHandler errorHandler = new ErrorHandler(); this.setActionHandler(handler); this.setRollbackHandler(errorHandler); } private class Delete extends Task { public Delete() { super(); } public int getQueueNumber() { return PriorityQueueScheduler.MANAGEMENT_QUEUE; } private void deleteForEndpoint(MgcpRequest request) { // getting endpoint name request.getEndpoint().divide('@', endpointName); // searching endpoint try { int n = transaction().find(localName, endpoints); if (n == 0) { throw new MgcpCommandException( MgcpResponseCode.ENDPOINT_NOT_AVAILABLE, new Text( "Endpoint not available")); } } catch (UnknownEndpointException e) { throw new MgcpCommandException( MgcpResponseCode.ENDPOINT_UNKNOWN, new Text( "Endpoint not available")); } // extract found endpoint endpoint = endpoints[0]; endpoint.deleteAllConnections(); } private void deleteForCall(Parameter callID, MgcpRequest request) { // getting call MgcpCall call = transaction().getCall( callID.getValue().hexToInteger(), false); if (call == null) { throw new MgcpCommandException( MgcpResponseCode.INCORRECT_CALL_ID, UNKNOWN_CALL_IDENTIFIER); } call.deleteConnections(); } @Override public long perform() { request = (MgcpRequest) getEvent().getMessage(); Parameter callID = request.getParameter(Parameter.CALL_ID); connectionID = request.getParameter(Parameter.CONNECTION_ID); if (callID == null && connectionID == null) { this.deleteForEndpoint(request); return 0; } if (callID != null && connectionID == null) { this.deleteForCall(callID, request); return 0; } if (callID == null) { throw new MgcpCommandException(MgcpResponseCode.PROTOCOL_ERROR, CALLID_MISSING); } // getting call MgcpCall call = transaction().getCall( callID.getValue().hexToInteger(), false); if (call == null) { throw new MgcpCommandException( MgcpResponseCode.INCORRECT_CALL_ID, UNKNOWN_CALL_IDENTIFIER); } if (connectionID == null) { throw new MgcpCommandException(MgcpResponseCode.PROTOCOL_ERROR, CONNECTIONID_EXPECTED); } // getting endpoint name request.getEndpoint().divide('@', endpointName); // searching endpoint try { int n = transaction().find(localName, endpoints); if (n == 0) { throw new MgcpCommandException( MgcpResponseCode.ENDPOINT_NOT_AVAILABLE, new Text( "Endpoint not available")); } } catch (UnknownEndpointException e) { throw new MgcpCommandException( MgcpResponseCode.ENDPOINT_UNKNOWN, new Text( "Endpoint not available")); } // extract found endpoint endpoint = endpoints[0]; MgcpConnection connection = endpoint.getConnection(connectionID .getValue().hexToInteger()); if (connection != null) { rx = connection.getPacketsReceived(); tx = connection.getPacketsTransmitted(); endpoint.deleteConnection(connectionID.getValue() .hexToInteger()); } return 0; } } /** * Searches endpoint specified in message. * * The result will be stored into variable endpoint. */ private class EndpointLocator extends Task { public EndpointLocator() { super(); } @Override public int getQueueNumber() { return PriorityQueueScheduler.MANAGEMENT_QUEUE; } @Override public long perform() { try { // searching endpoint int n = transaction().find(localName, endpoints); if (n == 0) { throw new MgcpCommandException(MgcpResponseCode.ENDPOINT_NOT_AVAILABLE, new Text("Endpoint not available")); } // extract found endpoint endpoint = endpoints[0]; // checking endpoint's state if (endpoint.getState() == MgcpEndpoint.STATE_BUSY) { throw new MgcpCommandException(MgcpResponseCode.ENDPOINT_NOT_AVAILABLE, new Text("Endpoint not available")); } } catch (Exception e) { throw new MgcpCommandException(MgcpResponseCode.ENDPOINT_NOT_AVAILABLE, new Text("Endpoint not available")); } return 0; } } private class Responder extends Task { public Responder() { super(); } @Override public int getQueueNumber() { return PriorityQueueScheduler.MANAGEMENT_QUEUE; } @Override public long perform() { MgcpEvent evt = transaction().getProvider().createEvent(MgcpEvent.RESPONSE, getEvent().getAddress()); MgcpResponse response = (MgcpResponse) evt.getMessage(); response.setResponseCode(MgcpResponseCode.TRANSACTION_WAS_EXECUTED); response.setResponseString(SUCCESS); response.setTxID(transaction().getId()); if (connectionID != null) { response.setParameter(Parameter.CONNECTION_ID, connectionID.getValue()); } response.setParameter(Parameter.CONNECTION_PARAMETERS, new Text("PS=" + tx + ", PR=" + rx)); try { transaction().getProvider().send(evt); } catch (IOException e) { logger.error(e); } finally { evt.recycle(); } return 0; } } private class ErrorHandler extends Task { public ErrorHandler() { super(); } @Override public int getQueueNumber() { return PriorityQueueScheduler.MANAGEMENT_QUEUE; } @Override public long perform() { code = ((MgcpCommandException) transaction().getLastError()).getCode(); message = ((MgcpCommandException) transaction().getLastError()).getErrorMessage(); MgcpEvent evt = transaction().getProvider().createEvent(MgcpEvent.RESPONSE, getEvent().getAddress()); MgcpResponse response = (MgcpResponse) evt.getMessage(); response.setResponseCode(code); response.setResponseString(message); response.setTxID(transaction().getId()); if (connectionID != null) { response.setParameter(Parameter.CONNECTION_ID, connectionID.getValue()); } try { transaction().getProvider().send(evt); } catch (IOException e) { logger.error(e); } finally { evt.recycle(); } return 0; } } }