/*
* 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.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.params.LocalConnectionOptions;
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.ModeNotSupportedException;
import org.restcomm.media.spi.utils.Text;
import org.apache.log4j.Logger;
/**
* Modify connection command.
*
* @author Oifa Yulian
*/
public class ModifyConnectionCmd 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 SDP_NEGOTIATION_FAILED = new Text("SDP_NEGOTIATION_FAILED");
private final static Text SUCCESS= new Text("Success");
private MgcpRequest request;
private Parameter connectionID;
private TaskChain handler;
//error code and message
private int code;
private Text message;
private MgcpConnection mgcpConnection = null;
//local connection options
private LocalConnectionOptions lcOptions = new LocalConnectionOptions();
private final static Logger logger = Logger.getLogger(ModifyConnectionCmd.class);
public ModifyConnectionCmd(Scheduler scheduler) {
handler = new TaskChain(1,scheduler);
Modifier modifier = new Modifier();
handler.add(modifier);
ErrorHandler errorHandler = new ErrorHandler();
this.setActionHandler(handler);
this.setRollbackHandler(errorHandler);
}
private class Modifier extends Task {
public Modifier() {
super();
}
public int getQueueNumber()
{
return PriorityQueueScheduler.MANAGEMENT_QUEUE;
}
@Override
public long perform() {
request = (MgcpRequest) getEvent().getMessage();
Parameter callID = request.getParameter(Parameter.CALL_ID);
if (callID == null) {
throw new MgcpCommandException(MgcpResponseCode.PROTOCOL_ERROR, CALLID_MISSING);
}
//modify local connection options
Parameter l = request.getParameter(Parameter.LOCAL_CONNECTION_OPTIONS);
if (l != null) {
lcOptions.setValue(l.getValue());
} else {
lcOptions.setValue(null);
}
//getting call
MgcpCall call = transaction().getCall(callID.getValue().hexToInteger(), false);
if (call == null) {
throw new MgcpCommandException(MgcpResponseCode.INCORRECT_CALL_ID, UNKNOWN_CALL_IDENTIFIER);
}
connectionID = request.getParameter(Parameter.CONNECTION_ID);
if (connectionID == null) {
throw new MgcpCommandException(MgcpResponseCode.PROTOCOL_ERROR, CONNECTIONID_EXPECTED);
}
try {
mgcpConnection = call.getMgcpConnection(connectionID.getValue().hexToInteger());
} catch (Exception e) {
throw new MgcpCommandException(MgcpResponseCode.CONNECTION_WAS_DELETED, new Text("Unknown connectionidentifier, probably it was deleted"));
}
if(mgcpConnection==null)
throw new MgcpCommandException(MgcpResponseCode.CONNECTION_WAS_DELETED, new Text("Unknown connectionidentifier, probably it was deleted"));
//set SDP if requested
Parameter sdp = request.getParameter(Parameter.SDP);
Parameter mode = request.getParameter(Parameter.MODE);
if (sdp != null) {
try {
mgcpConnection.setOtherParty(sdp.getValue());
} catch (IOException e) {
logger.error("Could not set remote peer", e);
throw new MgcpCommandException(MgcpResponseCode.UNSUPPORTED_SDP, SDP_NEGOTIATION_FAILED);
}
}
if (mode != null) {
try {
mgcpConnection.setMode(mode.getValue());
} catch (ModeNotSupportedException e) {
throw new MgcpCommandException(MgcpResponseCode.INVALID_OR_UNSUPPORTED_MODE, new Text("problem with mode"));
}
}
mgcpConnection.setDtmfClamp(lcOptions.getDtmfClamp());
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());
}
Text descriptor=mgcpConnection.getDescriptor();
if(descriptor!=null)
response.setParameter(Parameter.SDP, mgcpConnection.getDescriptor());
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;
}
}
}