/*
* TeleStax, Open Source Cloud Communications
* Copyright 2012, Telestax 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.
*/
/**
* Start time:12:14:57 2009-09-04<br>
* Project: mobicents-isup-stack<br>
*
* @author <a href="mailto:baranowb@gmail.com">Bartosz Baranowski </a>
*/
package org.mobicents.protocols.ss7.isup.impl;
import java.io.IOException;
import org.apache.log4j.Logger;
import org.mobicents.protocols.ss7.isup.CircuitManager;
import org.mobicents.protocols.ss7.isup.ISUPMessageFactory;
import org.mobicents.protocols.ss7.isup.ISUPParameterFactory;
import org.mobicents.protocols.ss7.isup.ISUPProvider;
import org.mobicents.protocols.ss7.isup.ISUPStack;
import org.mobicents.protocols.ss7.isup.ParameterException;
import org.mobicents.protocols.ss7.isup.impl.message.AbstractISUPMessage;
import org.mobicents.protocols.ss7.mtp.Mtp3;
import org.mobicents.protocols.ss7.mtp.Mtp3EndCongestionPrimitive;
import org.mobicents.protocols.ss7.mtp.Mtp3PausePrimitive;
import org.mobicents.protocols.ss7.mtp.Mtp3ResumePrimitive;
import org.mobicents.protocols.ss7.mtp.Mtp3StatusPrimitive;
import org.mobicents.protocols.ss7.mtp.Mtp3TransferPrimitive;
import org.mobicents.protocols.ss7.mtp.Mtp3UserPart;
import org.mobicents.protocols.ss7.mtp.Mtp3UserPartListener;
import org.mobicents.protocols.ss7.scheduler.Scheduler;
/**
* Start time:12:14:57 2009-09-04<br>
* Project: mobicents-isup-stack<br>
*
* @author <a href="mailto:baranowb@gmail.com">Bartosz Baranowski </a>
*/
public class ISUPStackImpl implements ISUPStack, Mtp3UserPartListener {
private Logger logger = Logger.getLogger(ISUPStackImpl.class);
private State state = State.IDLE;
private Mtp3UserPart mtp3UserPart = null;
private CircuitManager circuitManager = null;
private ISUPProviderImpl provider;
// local vars
private ISUPMessageFactory messageFactory;
private ISUPParameterFactory parameterFactory;
private Scheduler scheduler;
public ISUPStackImpl(final Scheduler scheduler, final int localSpc, final int ni, final boolean automaticTimerMessages) {
super();
this.scheduler = scheduler;
this.provider = new ISUPProviderImpl(this, scheduler, ni, localSpc, automaticTimerMessages);
this.parameterFactory = this.provider.getParameterFactory();
this.messageFactory = this.provider.getMessageFactory();
this.state = State.CONFIGURED;
}
public ISUPStackImpl(Scheduler scheduler, int localSpc, int ni) {
this(scheduler, localSpc, ni, true);
}
public ISUPProvider getIsupProvider() {
return provider;
}
public void start() throws IllegalStateException {
if (state != State.CONFIGURED) {
throw new IllegalStateException("Stack has not been configured or is already running!");
}
if (state == State.RUNNING) {
// throw new StartFailedException("Can not start stack again!");
throw new IllegalStateException("Can not start stack again!");
}
if (this.mtp3UserPart == null) {
throw new IllegalStateException("No Mtp3UserPart present!");
}
if (this.circuitManager == null) {
throw new IllegalStateException("No CircuitManager present!");
}
// this.executor = Executors.newFixedThreadPool(1);
// this.layer3exec = Executors.newFixedThreadPool(1);
this.provider.start();
// this.layer3exec.execute(new MtpStreamHandler());
this.mtp3UserPart.addMtp3UserPartListener(this);
this.state = State.RUNNING;
}
public void stop() {
if (state != State.RUNNING) {
throw new IllegalStateException("Stack is not running!");
}
// if(state == State.CONFIGURED)
// {
// throw new IllegalStateException("Can not stop stack again!");
// }
this.mtp3UserPart.removeMtp3UserPartListener(this);
// this.executor.shutdown();
// this.layer3exec.shutdown();
this.provider.stop();
this.state = State.CONFIGURED;
}
// ///////////////
// CONF METHOD //
// ///////////////
/**
*
*/
public Mtp3UserPart getMtp3UserPart() {
return mtp3UserPart;
}
public void setMtp3UserPart(Mtp3UserPart mtp3UserPart) {
this.mtp3UserPart = mtp3UserPart;
}
public void setCircuitManager(CircuitManager mgr) {
this.circuitManager = mgr;
}
public CircuitManager getCircuitManager() {
return this.circuitManager;
}
// ---------------- private methods and class defs
/**
* @param message
*/
void send(Mtp3TransferPrimitive message) throws IOException {
if (this.state != State.RUNNING)
return;
// here we have encoded msg, nothing more, need to add MTP3 label.
// txDataQueue.add(message);
try {
this.mtp3UserPart.sendMessage(message);
} catch (IOException e) {
// log here Exceptions from MTP3 level
logger.error("IOException when sending the message to MTP3 level: " + e.getMessage(), e);
e.printStackTrace();
throw e;
}
}
private enum State {
IDLE, CONFIGURED, RUNNING;
}
@Override
public void onMtp3PauseMessage(Mtp3PausePrimitive arg0) {
// TODO Auto-generated method stub
}
@Override
public void onMtp3ResumeMessage(Mtp3ResumePrimitive arg0) {
// TODO Auto-generated method stub
}
@Override
public void onMtp3StatusMessage(Mtp3StatusPrimitive arg0) {
// TODO Auto-generated method stub
}
@Override
public void onMtp3EndCongestionMessage(Mtp3EndCongestionPrimitive msg) {
// TODO Auto-generated method stub
}
@Override
public void onMtp3TransferMessage(Mtp3TransferPrimitive mtpMsg) {
if (this.state != State.RUNNING)
return;
// process only ISUP messages
if (mtpMsg.getSi() != Mtp3._SI_SERVICE_ISUP)
return;
// 2(CIC) + 1(CODE)
byte[] payload = mtpMsg.getData();
int commandCode = payload[2];
AbstractISUPMessage msg = (AbstractISUPMessage) messageFactory.createCommand(commandCode);
try {
msg.decode(payload,messageFactory, parameterFactory);
} catch (ParameterException e) {
logger.error("Error decoding of incoming Mtp3TransferPrimitive" + e.getMessage(), e);
e.printStackTrace();
}
msg.setSls(mtpMsg.getSls()); // store SLS...
// should take here OPC or DPC????? since come in different direction looks like opc
provider.receive(msg, mtpMsg.getOpc());
}
// private class MtpStreamHandler implements Runnable {
// ByteBuffer rxBuffer = ByteBuffer.allocateDirect(1000);
// ByteBuffer txBuffer = ByteBuffer.allocateDirect(1000);
// int rxBytes = 0;
// @SuppressWarnings("unused")
// int txBytes = 0;
//
// public void run() {
// // Execute only till state is Running
// while (state == State.RUNNING) {
//
// try {
// //Execute the MTP3UserPart
// mtp3UserPart.execute();
//
// rxBytes = 0;
// rxBuffer.clear();
// try {
// rxBytes = mtp3UserPart.read(rxBuffer);
// if (rxBytes != 0) {
// byte[] data = new byte[rxBytes];
// rxBuffer.flip();
// rxBuffer.get(data);
// MessageHandler handler = new MessageHandler(data);
// executor.execute(handler);
// }
// } catch (IOException e) {
// logger.error("Error while readig data from Mtp3UserPart", e);
// }
//
// // Iterate till we send all data
// while (!txDataQueue.isEmpty()) {
// txBuffer.clear();
// txBuffer.put(txDataQueue.poll());
// txBuffer.flip();
// try {
// txBytes = mtp3UserPart.write(txBuffer);
// } catch (IOException e) {
// logger.error("Error while writting data to Mtp3UserPart", e);
// }
// }// while txDataQueue
// } catch (IOException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
// }// end of while
// }
// }
//
// private class MessageHandler implements Runnable {
// // MSU as input stream
// private byte[] msu;
// private ISUPMessage message;
//
// protected MessageHandler(byte[] msu) {
// this.msu = msu;
//
// }
//
// private ISUPMessage parse() throws IOException {
// try {
// // FIXME: change this, dont copy over and over?
//
// int commandCode = msu[7];// 1(SIO) + 3(RL) + 1(SLS) + 2(CIC) + 1(CODE)
// // http://pt.com/page/tutorials/ss7-tutorial/mtp
// byte[] payload = new byte[msu.length - 5];
// System.arraycopy(msu, 5, payload, 0, payload.length);
// byte sls = msu[5];
// // for post processing
// AbstractISUPMessage msg = (AbstractISUPMessage)
// messageFactory.createCommand(commandCode);
// msg.decode(payload, parameterFactory);
// msg.setSls(sls); //store SLS...
// return msg;
//
// } catch (Exception e) {
// // FIXME: what should we do here? send back?
// e.printStackTrace();
// logger.error("Failed on data: " + Utils.hexDump(null, msu));
// }
// return null;
// }
//
// public void run() {
// if (message == null) {
// try {
// message = parse();
// } catch (IOException e) {
// logger.warn("Corrupted message received");
// return;
// }
// }
// // deliver to provider, so it can check up on circuit, play with
// // timers and deliver.
// if(message!=null)
// {
// try{
// provider.receive(message);
// }catch(Exception e)
// {
// //TODO: add proper answer?
// }
// }
// }
// }
}