/*
* 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.
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.restcomm.media.rtp;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.restcomm.media.codec.g711.alaw.Decoder;
import org.restcomm.media.codec.g711.alaw.Encoder;
import org.restcomm.media.component.audio.AudioComponent;
import org.restcomm.media.component.audio.AudioMixer;
import org.restcomm.media.component.dsp.Dsp;
import org.restcomm.media.component.dsp.DspFactoryImpl;
import org.restcomm.media.component.oob.OOBComponent;
import org.restcomm.media.component.oob.OOBMixer;
import org.restcomm.media.network.deprecated.RtpPortManager;
import org.restcomm.media.network.deprecated.UdpManager;
import org.restcomm.media.resource.dtmf.DetectorImpl;
import org.restcomm.media.rtp.crypto.DtlsSrtpServer;
import org.restcomm.media.rtp.crypto.DtlsSrtpServerProvider;
import org.restcomm.media.scheduler.Clock;
import org.restcomm.media.scheduler.PriorityQueueScheduler;
import org.restcomm.media.scheduler.Scheduler;
import org.restcomm.media.scheduler.ServiceScheduler;
import org.restcomm.media.scheduler.WallClock;
import org.restcomm.media.sdp.format.AVProfile;
import org.restcomm.media.spi.ConnectionMode;
import org.restcomm.media.spi.dtmf.DtmfDetectorListener;
import org.restcomm.media.spi.dtmf.DtmfEvent;
import org.restcomm.media.spi.format.AudioFormat;
import org.restcomm.media.spi.format.FormatFactory;
import org.restcomm.media.spi.format.Formats;
/**
*
* @author oifa yulian
*/
public class RTPEventTest implements DtmfDetectorListener {
//clock and scheduler
private Clock clock;
private PriorityQueueScheduler mediaScheduler;
private Scheduler scheduler;
private ChannelsManager channelsManager;
private UdpManager udpManager;
// private SpectraAnalyzer analyzer;
private DetectorImpl detector;
private RTPDataChannel channel;
private DspFactoryImpl dspFactory = new DspFactoryImpl();
private Dsp dsp11, dsp12;
private Dsp dsp21, dsp22;
private Sender sender;
private AudioMixer audioMixer;
private OOBMixer oobMixer;
private AudioComponent detectorComponent;
private OOBComponent oobComponent;
private int count=0;
private static final int cipherSuites[] = { 0xc030, 0xc02f, 0xc028, 0xc027, 0xc014, 0xc013, 0x009f, 0x009e, 0x006b, 0x0067,
0x0039, 0x0033, 0x009d, 0x009c, 0x003d, 0x003c, 0x0035, 0x002f, 0xc02b };
public RTPEventTest() {
scheduler = new ServiceScheduler();
}
@Before
public void setUp() throws Exception {
// given
DtlsSrtpServerProvider mockedDtlsServerProvider = mock(DtlsSrtpServerProvider.class);
DtlsSrtpServer mockedDtlsSrtpServer = mock(DtlsSrtpServer.class);
// when
when(mockedDtlsServerProvider.provide()).thenReturn(mockedDtlsSrtpServer);
when(mockedDtlsSrtpServer.getCipherSuites()).thenReturn(cipherSuites);
// then
AudioFormat pcma = FormatFactory.createAudioFormat("pcma", 8000, 8, 1);
Formats fmts = new Formats();
fmts.add(pcma);
Formats dstFormats = new Formats();
dstFormats.add(FormatFactory.createAudioFormat("LINEAR", 8000, 16, 1));
dspFactory.addCodec(Encoder.class.getName());
dspFactory.addCodec(Decoder.class.getName());
dsp11 = dspFactory.newProcessor();
dsp12 = dspFactory.newProcessor();
dsp21 = dspFactory.newProcessor();
dsp22 = dspFactory.newProcessor();
//use default clock
clock = new WallClock();
//create single thread scheduler
mediaScheduler = new PriorityQueueScheduler();
mediaScheduler.setClock(clock);
mediaScheduler.start();
udpManager = new UdpManager(scheduler, new RtpPortManager(), new RtpPortManager());
scheduler.start();
udpManager.start();
channelsManager = new ChannelsManager(udpManager, mockedDtlsServerProvider);
channelsManager.setScheduler(mediaScheduler);
detector = new DetectorImpl("dtmf", -35, 40, 100, mediaScheduler);
detector.addListener(this);
channel = channelsManager.getChannel();
channel.bind(false);
sender = new Sender(channel.getLocalPort());
channel.setPeer(new InetSocketAddress("127.0.0.1", 9200));
channel.setInputDsp(dsp11);
channel.setFormatMap(AVProfile.audio);
audioMixer=new AudioMixer(mediaScheduler);
audioMixer.addComponent(channel.getAudioComponent());
detectorComponent=new AudioComponent(1);
detectorComponent.addOutput(detector.getAudioOutput());
detectorComponent.updateMode(true,true);
audioMixer.addComponent(detectorComponent);
oobMixer=new OOBMixer(mediaScheduler);
oobMixer.addComponent(channel.getOOBComponent());
oobComponent=new OOBComponent(1);
oobComponent.addOutput(detector.getOOBOutput());
oobComponent.updateMode(true,true);
oobMixer.addComponent(oobComponent);
}
@After
public void tearDown() {
channel.close();
audioMixer.stop();
oobMixer.stop();
udpManager.stop();
mediaScheduler.stop();
scheduler.stop();
sender.close();
}
@Test
public void testTransmission() throws Exception {
channel.updateMode(ConnectionMode.SEND_RECV);
audioMixer.start();
oobMixer.start();
detector.activate();
new Thread(sender).start();
Thread.sleep(5000);
channel.updateMode(ConnectionMode.INACTIVE);
audioMixer.stop();
oobMixer.stop();
detector.deactivate();
assertEquals(4,count);
}
public void process(DtmfEvent event) {
count++;
System.out.println("TONE=" + event.getTone());
}
private class Sender implements Runnable {
private DatagramSocket socket;
private ArrayList<byte[]> stream = new ArrayList<byte[]>();
private int port;
private InetSocketAddress dst;
private byte[][] evt = new byte[][]{
new byte[] {0x03, 0x0a, 0x00, (byte)0xa0},
new byte[] {0x03, 0x0a, 0x01, (byte)0x40},
new byte[] {0x03, 0x0a, 0x01, (byte)0xe0}
};
private byte[][] evt1 = new byte[][]{
new byte[] {0x0b, 0x0a, 0x00, (byte)0xa0},
new byte[] {0x0b, 0x0a, 0x01, (byte)0x40},
new byte[] {0x0b, 0x0a, 0x01, (byte)0xe0},
new byte[] {0x0b, 0x0a, 0x02, (byte)0x80},
new byte[] {0x0b, 0x0a, 0x03, (byte)0x20},
new byte[] {0x0b, 0x0a, 0x03, (byte)0xc0},
new byte[] {0x0b, 0x0a, 0x04, (byte)0x60},
new byte[] {0x0b, 0x0a, 0x05, (byte)0x00},
new byte[] {0x0b, (byte)0x8a, 0x05, (byte)0xa0},
new byte[] {0x0b, (byte)0x8a, 0x05, (byte)0xa0},
new byte[] {0x0b, (byte)0x8a, 0x05, (byte)0xa0}
};
//lets make empty content for alaw
private byte[] zeroContent=new byte[160];
public Sender(int port) throws SocketException {
for(int i=0;i<zeroContent.length;i++)
zeroContent[i]=(byte)0xD5;
this.port = port;
dst = new InetSocketAddress("127.0.0.1", port);
socket = new DatagramSocket(new InetSocketAddress("127.0.0.1", 9200));
this.generateSequence(250);
}
private void generateSequence(int len) {
boolean event = false;
boolean marker = false;
int t=0;
int count = 0;
int it = 12345;
for (int i = 0; i < len; i++) {
RtpPacket p = new RtpPacket(172, false);
if (i % 50 == 0 && i > 0) {
event = true;
marker = true;
t = 160 * (i + 1);
count = 0;
}
if (event) {
p.wrap(marker, 101, i + 1, t + it, 123, evt1[count++], 0, 4);
marker = false;
if (count == evt1.length) {
event = false;
}
} else {
p.wrap(marker, 8, i + 1, 160 * (i + 1) + it, 123, zeroContent, 0, 160);
}
byte[] data = new byte[p.getBuffer().limit()];
p.getBuffer().get(data);
stream.add(data);
}
}
@Override
public void run() {
while (!stream.isEmpty()) {
byte[] data = stream.remove(0);
try {
DatagramPacket p = new DatagramPacket(data, 0, data.length, dst);
socket.send(p);
Thread.sleep(20);
} catch (Exception e) {
}
}
}
public void close() {
if (socket != null) {
socket.close();
}
}
}
}