/*
* Mobicents, Communications Middleware
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party
* contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
*
* Boston, MA 02110-1301 USA
*/
package org.mobicents.media.server.impl.resource.ss7;
import java.io.IOException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
/**
*
* @author kulikov
*/
public class Mtp3 {
private final static int T1 = 12;
private final static int T2 = 90;
private final static int LINK_MANAGEMENT = 0;
private final static int LINK_TESTING = 1;
private final static int SERVICE_SCCP = 3;
private final static int SERVICE_ISUP= 5;
private Mtp2 layer2;
private ScheduledFuture t1;
private ScheduledFuture t2;
private int destinationPointCode;
private int originationPointCode;
private int signalingLinkSelection;
private final static byte[] PATTERN = new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0F};
private T1Action t1Action = new T1Action();
private T2Action t2Action = new T2Action();
private String name;
private Logger logger = Logger.getLogger(Mtp3.class);
public Mtp3(String name) {
this.name = name;
layer2 = new Mtp2(name);
layer2.setLayer3(this);
}
public void setOPC(int opc) {
this.originationPointCode = opc;
}
public void setDPC(int dpc) {
this.destinationPointCode = dpc;
}
public void setSLS(int sls) {
this.signalingLinkSelection = sls;
}
public void start() throws IOException {
layer2.start();
}
public void stop() {
if (t2 != null && !t2.isCancelled()) {
t2.cancel(false);
}
t2.cancel(false);
layer2.stop();
}
/**
*
* @param sio service information octet.
* @param msg service information field;
*/
public void onMessage(int sio, byte[] sif) {
int ni = sio >>> 6;
int piority = (sio >>> 4 & 0x03);
int si = sio & 0x0f;
int dpc = (sif[0] & 0xff | ((sif[1] & 0x3f) << 8));
int opc = ((sif[1] & 0x03) >> 6) | ((sif[2] & 0xff) << 2) | ((sif[3] & 0x0f) << 10);
int sls = (sif[3] & 0xf0) >>> 4;
if (logger.isDebugEnabled()) {
logger.debug("Received MSSU [si=" + si + ", dpc=" + dpc + ", opc=" + opc + ", sls=" + sls + "]");
}
switch (si) {
case LINK_MANAGEMENT :
break;
case LINK_TESTING :
int h0 = sif[4] & 0x0f;
int h1 = (sif[4] & 0xf0) >>> 4;
int len = (sif[5] & 0xf0) >>> 4;
if (h0 == 1 && h1 == 1) {
if (logger.isDebugEnabled()) {
logger.debug("SLTM received");
}
//receive SLTM from remote end
//create response
byte[] slta = new byte[len + 6];
slta[0] = (byte)sio;
writeRoutingLabel(slta);
slta[5] = 0x021;
System.arraycopy(sif, 5, slta, 6, len);
layer2.queue(slta);
if (logger.isDebugEnabled()) {
logger.debug("Responding with SLTA");
}
} else if (h0 == 1 && h1 == 2) {
//receive SLTA from remote end
if (logger.isDebugEnabled()) {
logger.debug("Link(" + name + ") SLTA received");
}
//stop Q707 timer T1
if (t1 != null && !t1.isCancelled()) {
t1.cancel(false);
}
//check contidions for acceptance
if (opc != this.destinationPointCode) {
return;
}
if (dpc != this.originationPointCode) {
return;
}
if (!checkPattern(sif, PATTERN)) {
return;
}
logger.info("Notify layer 4");
//notify level 4
} else {
logger.warn("Unexpected message type");
}
break;
case SERVICE_SCCP :
break;
case SERVICE_ISUP :
break;
}
}
public void send(byte[] msg) {
}
public void failed() {
}
public void inService() {
t2 = Mtp2.mtpTimer.scheduleAtFixedRate(new LinkTest(), 0, T2, TimeUnit.SECONDS);
}
/**
* Assigns layer 1 implementation.
*
* @param layer1 the implementation of MTP1 layer.
*/
public void setLayer1(Mtp1 layer1) {
layer2.setLayer1(layer1);
}
private void sendSLTM() {
byte[] sltm = new byte[7 + PATTERN.length];
sltm[0] = 1;
writeRoutingLabel(sltm);
sltm[5] = 0x11;
sltm[6] = (byte)(PATTERN.length << 4);
System.arraycopy(PATTERN, 0, sltm, 7, PATTERN.length);
layer2.queue(sltm);
Mtp2.mtpTimer.schedule(t1Action, T1, TimeUnit.SECONDS);
if (logger.isDebugEnabled()) {
logger.debug("Link (" + name + ") Queue SLTM");
}
}
private void writeRoutingLabel(byte[] sif) {
sif[1] = (byte) destinationPointCode;
sif[2] = (byte)(((destinationPointCode >> 8) & 0x3f) |((destinationPointCode & 0x03) << 6));
sif[3] = (byte)(originationPointCode >> 2);
sif[4] = (byte)(((originationPointCode >> 10) & 0x0f)| (signalingLinkSelection << 4));
}
private boolean checkPattern(byte[] sif, byte[] pattern) {
if (sif.length - 5 != pattern.length) {
return false;
}
for (int i = 0; i < pattern.length; i++) {
if (sif[i + 5] != pattern[i]) {
return false;
}
}
return true;
}
private class LinkTest implements Runnable {
public void run() {
sendSLTM();
}
}
private class T1Action implements Runnable {
public void run() {
}
}
private class T2Action implements Runnable {
public void run() {
}
}
}