/*
* TeleStax, Open Source Cloud Communications Copyright 2012.
* 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.mobicents.protocols.ss7.sccp.impl;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
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.Mtp3StatusCause;
import org.mobicents.protocols.ss7.mtp.Mtp3StatusPrimitive;
import org.mobicents.protocols.ss7.mtp.Mtp3TransferPrimitive;
import org.mobicents.protocols.ss7.mtp.Mtp3TransferPrimitiveFactory;
import org.mobicents.protocols.ss7.mtp.Mtp3UserPartBaseImpl;
/**
* @author abhayani
* @author baranowb
* @author sergey vetyutnev
*/
public class Mtp3UserPartImpl extends Mtp3UserPartBaseImpl {
// protected ConcurrentLinkedQueue<byte[]> readFrom;
// protected ConcurrentLinkedQueue<byte[]> writeTo;
private Mtp3UserPartImpl otherPart;
private ArrayList<Mtp3TransferPrimitive> messages = new ArrayList<Mtp3TransferPrimitive>();
protected boolean saveTrafficInFile = false;
public Mtp3UserPartImpl() {
super(null);
try {
this.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void setOtherPart(Mtp3UserPartImpl otherPart) {
this.otherPart = otherPart;
}
private int tsnNum = (new Random()).nextInt(1000);
public void sendMessage(Mtp3TransferPrimitive msg) throws IOException {
if (saveTrafficInFile) {
try {
// pcap version
// m3ua part
byte[] sccpPart = msg.getData();
ByteArrayOutputStream stm1 = new ByteArrayOutputStream();
stm1.write(1); // m3ua version - release 1
stm1.write(0); // m3ua reserved
stm1.write(1); // m3ua message class - Transfer message
stm1.write(1); // m3ua Message type - Payload data
int lenb = sccpPart.length + 16;
int lena = lenb + 8;
int m3uaPad = lena % 4;
if (m3uaPad > 0)
m3uaPad = 4 - m3uaPad;
lena += m3uaPad;
stm1.write(0); // m3ua Payload data length
stm1.write(0);
stm1.write(lena / 256);
stm1.write(lena % 256);
stm1.write(2); // Parameter tag: protocol data
stm1.write(0x10);
stm1.write(lenb / 256); // protocol data length
stm1.write(lenb % 256);
stm1.write(0); // m3ua opc
stm1.write(0);
stm1.write(msg.getOpc() / 256);
stm1.write(msg.getOpc() % 256);
stm1.write(0); // m3ua dpc
stm1.write(0);
stm1.write(msg.getDpc() / 256);
stm1.write(msg.getDpc() % 256);
stm1.write(msg.getSi());
stm1.write(msg.getNi());
stm1.write(msg.getMp());
stm1.write(msg.getSls());
stm1.write(sccpPart);
for (int i1 = 0; i1 < m3uaPad; i1++) {
stm1.write(0);
}
byte[] m3uaPart = stm1.toByteArray();
// sctp part
ByteArrayOutputStream stm2 = new ByteArrayOutputStream();
stm2.write(1); // source port
stm2.write(1);
stm2.write(2); // dest port
stm2.write(2);
stm2.write(3); // verification tag
stm2.write(3);
stm2.write(3);
stm2.write(3);
stm2.write(4); // checksum - not really calculated
stm2.write(4);
stm2.write(4);
stm2.write(4);
int lenc = m3uaPart.length + 16;
stm2.write(0); // chunk type - data
stm2.write(3); // chunk flags
stm2.write(lenc / 256); // chunk length
stm2.write(lenc % 256);
tsnNum++;
stm2.write(tsnNum); // TSN
stm2.write(0);
stm2.write(0);
stm2.write(0);
stm2.write(0); // stream identifier
stm2.write(3);
stm2.write(11); // stream sequence number
stm2.write(11);
stm2.write(0); // protocol identifier - m3ua
stm2.write(0);
stm2.write(0);
stm2.write(3);
stm2.write(m3uaPart);
byte[] sctpPart = stm2.toByteArray();
// ip V4 part
ByteArrayOutputStream stm3 = new ByteArrayOutputStream();
int lend = sctpPart.length + 20;
stm3.write(0x45); // version 4 + headerLen=20
stm3.write(0xe0); // dscp + ecn
stm3.write(lend / 256); // total length
stm3.write(lend % 256);
stm3.write(10); // identification
stm3.write(11);
stm3.write(0); // flags + fragment offset
stm3.write(0);
stm3.write(0x40); // time to live
stm3.write(0x84); // protocol: sctp
stm3.write(0); // checksum: not really checked
stm3.write(0);
stm3.write(1); // source ip address
stm3.write(2);
stm3.write(3);
stm3.write(4);
stm3.write(4); // dest ip address
stm3.write(3);
stm3.write(2);
stm3.write(1);
stm3.write(sctpPart);
byte[] ipPart = stm3.toByteArray();
// calculating ip header checksum
int ix = 0;
for (int i1 = 0; i1 < 10; i1++) {
int ii1 = ipPart[i1 * 2] & 0xFF;
int ii2 = ipPart[i1 * 2 + 1] & 0xFF;
ix += (ii1 << 8) + ii2;
}
int iy = ix & 0xFFFF;
int iz = iy ^ 0xFFFF;
ipPart[10] = (byte) (iz / 256);
ipPart[11] = (byte) (iz % 256);
// Ethernet part
ByteArrayOutputStream stm4 = new ByteArrayOutputStream();
stm4.write(8); // source
stm4.write(8);
stm4.write(8);
stm4.write(8);
stm4.write(8);
stm4.write(8);
stm4.write(6); // destination
stm4.write(6);
stm4.write(6);
stm4.write(6);
stm4.write(6);
stm4.write(6);
stm4.write(8); // type: ip
stm4.write(0);
stm4.write(ipPart);
byte[] ethPart = stm4.toByteArray();
// pcap header
FileOutputStream fs = new FileOutputStream("MsgLog.pcap", true);
// FileOutputStream fs = new FileOutputStream(Util.getTmpTestDir() + File.separator + "MsgLog.pcap", true);
int ln = ethPart.length;
fs.write(0);
fs.write(0);
fs.write(0);
fs.write(0);
fs.write(0);
fs.write(0);
fs.write(0);
fs.write(0);
fs.write(ln % 256);
fs.write(ln / 256);
fs.write(0);
fs.write(0);
fs.write(ln % 256);
fs.write(ln / 256);
fs.write(0);
fs.write(0);
// pcap data
fs.write(ethPart);
fs.close();
// MsgLog.txt version
// byte[] txData = msg.encodeMtp3();
// FileOutputStream fs = new FileOutputStream("MsgLog.txt", true);
// int ln = txData.length;
// fs.write(ln & 0xFF);
// fs.write(ln >> 8);
// fs.write(txData);
// fs.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (this.otherPart != null)
this.otherPart.sendTransferMessageToLocalUser(msg, msg.getSls());
else
this.messages.add(msg);
}
public void sendTransferMessageToLocalUser(int opc, int dpc, byte[] data) {
int si = Mtp3._SI_SERVICE_SCCP;
int ni = 2;
int mp = 0;
int sls = 0;
Mtp3TransferPrimitiveFactory factory = this.getMtp3TransferPrimitiveFactory();
Mtp3TransferPrimitive msg = factory.createMtp3TransferPrimitive(si, ni, mp, opc, dpc, sls, data);
int seqControl = 0;
this.sendTransferMessageToLocalUser(msg, seqControl);
}
public void sendPauseMessageToLocalUser(int affectedDpc) {
Mtp3PausePrimitive msg = new Mtp3PausePrimitive(affectedDpc);
this.sendPauseMessageToLocalUser(msg);
}
public void sendResumeMessageToLocalUser(int affectedDpc) {
Mtp3ResumePrimitive msg = new Mtp3ResumePrimitive(affectedDpc);
this.sendResumeMessageToLocalUser(msg);
}
public void sendStatusMessageToLocalUser(int affectedDpc, Mtp3StatusCause cause, int congestionLevel, int userPartIdentity) {
Mtp3StatusPrimitive msg = new Mtp3StatusPrimitive(affectedDpc, cause, congestionLevel, userPartIdentity);
this.sendStatusMessageToLocalUser(msg);
}
public void sendEndCongestionMessageToLocalUser(int affectedDpc) {
Mtp3EndCongestionPrimitive msg = new Mtp3EndCongestionPrimitive(affectedDpc);
this.sendEndCongestionMessageToLocalUser(msg);
}
public List<Mtp3TransferPrimitive> getMessages() {
return messages;
}
@Override
public int getMaxUserDataLength(int dpc) {
return 1000;
}
}