/**
* Start time:10:17:34 2009-08-03<br>
* Project: mobicents-media-server-test-suite<br>
*
* @author <a href="mailto:baranowb@gmail.com">Bartosz Baranowski </a>
*/
package org.mobicents.media.server.testsuite.general.rtp;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import javax.sdp.Attribute;
import org.apache.log4j.Logger;
/**
* Start time:10:17:34 2009-08-03<br>
* Project: mobicents-media-server-test-suite<br>
*
* @author <a href="mailto:baranowb@gmail.com">Bartosz Baranowski</a>
*/
public class RtpSocketImpl implements RtpSocket {
private static final transient Logger log = Logger.getLogger(RtpSocketImpl.class);
private int localPort;
private String localAddress;
private int remotePort;
String remoteAddress;
private InetSocketAddress remoteInetSocketAddress = null;
// holder for dynamic payloads.
private Vector<Attribute> rtpMap = new Vector<Attribute>();
private final List<RtpSocketListener> dataSinks = new ArrayList<RtpSocketListener>();
private RtpSocketFactoryImpl rtpSocketFactoryImpl;
private DatagramChannel channel;
private DatagramSocket socket;
private SelectionKey key;
/**
*
* @param transceiver
* @param timer
* @param formatMap
* @param rtpSocketFactoryImpl2
*/
public RtpSocketImpl(Vector<Attribute> formatMap, RtpSocketFactoryImpl rtpSocketFactory) {
this.rtpSocketFactoryImpl = rtpSocketFactory;
this.rtpMap.addAll(formatMap);
this.localAddress = this.rtpSocketFactoryImpl.getBindAddress();
}
public int init(InetAddress localAddress, int lowPort, int highPort) throws SocketException, IOException {
if (this.key != null) {
this.key.cancel();
this.key = null;
}
channel = DatagramChannel.open();
channel.configureBlocking(false);
socket = channel.socket();
boolean bound = false;
this.localAddress = localAddress.getHostAddress();
this.localPort = lowPort;
// looking for first unused port
while (!bound) {
try {
// creating local address and trying to bind socket to this
// address
InetSocketAddress bindAddress = new InetSocketAddress(localAddress, localPort);
socket.bind(bindAddress);
bound = true;
// if stunHost is assigned then stun ussage is supposed
// discovering paublic address
} catch (SocketException e) {
// increment port number util upper limit is not reached
localPort++;
if (localPort > highPort) {
throw e;
}
}
}
return localPort;
}
/*
* (non-Javadoc)
*
* @see org.mobicents.media.server.testsuite.general.rtp.RtpSocket#addListener
* (org.mobicents.media.server.testsuite.general.rtp.RtpSocketListener)
*/
public void addListener(RtpSocketListener listener) {
this.dataSinks.add(listener);
}
/*
* (non-Javadoc)
*
* @see org.mobicents.media.server.testsuite.general.rtp.RtpSocket#removeListener
* (org.mobicents.media.server.testsuite.general.rtp.RtpSocketListener)
*/
public void removeListener(RtpSocketListener listener) {
this.dataSinks.remove(listener);
}
public void resetRtpMap() {
this.rtpMap.clear();
this.rtpMap.addAll(this.rtpSocketFactoryImpl.getFormatMap());
}
public boolean isChannelOpen() {
return (this.channel != null && this.channel.isOpen());
}
public void release() {
this.resetRtpMap();
if (socket != null) {
socket.disconnect();
// socket.close();
}
dataSinks.clear();
this.rtpSocketFactoryImpl.releaseSocket(this);
}
/**
* Closes socket
*
*/
public void close() {
if (channel != null) {
try {
channel.disconnect();
} catch (IOException e) {
}
}
}
/**
* Assigns remote end.
*
* @param address
* the address of the remote party.
* @param port
* the port number of the remote party.
*/
public void setPeer(InetAddress address, int port) throws IOException {
remoteAddress = address.getHostAddress();
remotePort = port;
remoteInetSocketAddress = new InetSocketAddress(remoteAddress, remotePort);
channel.connect(remoteInetSocketAddress);
this.key = rtpSocketFactoryImpl.registerSocket(this);
if (log.isDebugEnabled()) {
log.debug("Connect RTP socket[" + localAddress + ":" + localPort + " to " + remoteAddress + ":"
+ remotePort);
}
}
/**
* Gets address to which this socked is bound.
*
* @return either local address to which this socket is bound
*/
public String getLocalAddress() {
return localAddress;
}
/**
* Returns port number to which this socked is bound.
*
* @return port number or -1 if socket not bound.
*/
public int getLocalPort() {
return localPort;
}
public void notify(Exception e) {
for (RtpSocketListener l : this.dataSinks)
l.error(e);
}
/*
* (non-Javadoc)
*
* @see org.mobicents.media.server.testsuite.general.rtp.RtpSocket#receive(org
* .mobicents.media.server.testsuite.general.rtp.RtpPacket)
*/
public void receive(RtpPacket rtpPacket) {
for (RtpSocketListener l : this.dataSinks)
l.receive(rtpPacket);
}
/*
* (non-Javadoc)
*
* @see org.mobicents.media.server.testsuite.general.rtp.RtpSocket#getSelectionKey()
*/
public SelectionKey getSelectionKey() {
return this.key;
}
public void setSelectionKey(SelectionKey key) {
this.key = key;
}
public DatagramChannel getChannel() {
return this.channel;
}
}