/* * 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.controller; import java.net.InetSocketAddress; import java.util.Collection; import java.util.Iterator; import org.restcomm.media.concurrent.ConcurrentCyclicFIFO; import org.restcomm.media.control.mgcp.MgcpEvent; import org.restcomm.media.control.mgcp.controller.signal.MgcpPackage; import org.restcomm.media.control.mgcp.controller.signal.Signal; import org.restcomm.media.control.mgcp.message.MgcpRequest; import org.restcomm.media.control.mgcp.message.Parameter; import org.restcomm.media.spi.Connection; import org.restcomm.media.spi.Endpoint; import org.restcomm.media.spi.utils.Text; /** * * @author kulikov */ public class Request { //request identifier provided by call agent. private Text ID = new Text(new byte[15], 0, 15); //notified entity parameter private NotifiedEntity callAgent = new NotifiedEntity(); //executors grouped into packages private Collection<MgcpPackage> packages; //currently running signal private Signal currentSignal; //Endpoint executing this request private MgcpEndpoint endpoint; /** * The list of signals/events requested. * This list is cleared each time before accept new request. */ private ConcurrentCyclicFIFO<Signal> executors = new ConcurrentCyclicFIFO<Signal>(); //notified entity address private InetSocketAddress address; public Request(MgcpEndpoint endpoint, Collection<MgcpPackage> packages) { this.endpoint = endpoint; this.packages = packages; this.setRequest(); } /** * Assigns this request executor to each package. */ private void setRequest() { for (MgcpPackage p : packages) { p.setRequest(this); } } /** * Extracts signals and events from the given MGCP message and prepares * request for execution. * * @param ID the identifier of the request provided by the call agent. * @param events the requested events parameter * @param signals the requested signals parameter */ public void accept(Text ID, Text callAgent, Collection<Text> events, Collection<Text> signals) throws UnknownPackageException, UnknownEventException, UnknownSignalException { //clean previously requested events and signals executors.clear(); //reset packages for (MgcpPackage p : packages) { p.reset(); } //make a copy of the ID parameter ID.duplicate(this.ID); //make a copy of call agent parameter this.callAgent.setValue(callAgent); //queue events if (events != null) { Iterator<Text> it = events.iterator(); while (it.hasNext()) { Text evt = it.next(); queueEvent(evt); } } if (signals != null) { Iterator<Text> it = signals.iterator(); //queue signals while (it.hasNext()) { queueSignal(it.next()); } } } /** * Cancels execution of current request and cleans previously * requested signals/events. * */ public void cancel() { if (currentSignal != null) { currentSignal.cancel(); } } /** * Starts the execution of */ public void execute() { currentSignal = executors.poll(); if(currentSignal!=null) currentSignal.execute(); } public void onEvent(Text event) { address = new InetSocketAddress(callAgent.getHostName().toString(), callAgent.getPort()); MgcpEvent evt = (MgcpEvent) endpoint.mgcpProvider.createEvent(MgcpEvent.REQUEST, address); MgcpRequest msg = (MgcpRequest) evt.getMessage(); msg.setCommand(new Text("NTFY")); msg.setEndpoint(endpoint.fullName); msg.setParameter(Parameter.OBSERVED_EVENT, event); msg.setParameter(Parameter.NOTIFIED_ENTITY, callAgent.getValue()); msg.setParameter(Parameter.REQUEST_ID, ID); msg.setTxID(MgcpEndpoint.txID.incrementAndGet()); endpoint.send(evt, address); } public void completed() { //start next signal execute(); } public Endpoint getEndpoint() { return endpoint.getEndpoint(); } public NotifiedEntity getCallAgent() { return callAgent; } public Connection getConnection(String ID) throws UnknownActivityException { MgcpConnection mgcpConnection = this.endpoint.getConnection(Integer.valueOf(ID)); if(mgcpConnection == null) { return null; } return mgcpConnection.getConnection(); } private void queueEvent(Text event) throws UnknownPackageException, UnknownEventException { event.trim(); Text pkgName = new Text(); Text eventName = new Text(); Text[] evt = new Text[] {pkgName, eventName}; event.divide('/', evt); MgcpPackage p = this.getPackage(pkgName); if (p == null) { throw new UnknownPackageException(eventName.toString()); } p.accept(eventName); } private void queueSignal(Text event) throws UnknownPackageException, UnknownSignalException { Text pkgName = new Text(); Text eventName = new Text(); Text[] evt = new Text[] {pkgName, eventName}; event.divide('/', evt); Text signalName = new Text(); Text options = new Text(); Text[] signal = new Text[]{signalName, options}; eventName.divide(new char[]{'(', ')'}, signal); MgcpPackage p = this.getPackage(pkgName); Signal s = p.getSignal(signalName); if (s == null) { throw new UnknownSignalException(eventName.toString()); } s.setTrigger(pkgName, eventName, options); executors.offer(s); } private MgcpPackage getPackage(Text name) throws UnknownPackageException { for (MgcpPackage p : packages) { if (p.getName().equals(name)) { return p; } } throw new UnknownPackageException(name.toString()); } }