/* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package net.java.sip.communicator.impl.neomedia; import java.io.*; import java.net.*; import javax.media.rtp.*; import net.java.sip.communicator.service.neomedia.*; /** * @author Bing SU (nova.su@gmail.com) * @author Lubomir Marinov */ public class RTPConnectorImpl implements RTPConnector { /** * The pair of datagram sockets for RTP and RTCP traffic that this instance * uses in the form of a StreamConnector. */ private final StreamConnector connector; /** * RTCP packet input stream used by RTPManager. */ private RTPConnectorInputStream controlInputStream; /** * RTCP packet output stream used by RTPManager. */ private RTPConnectorOutputStream controlOutputStream; /** * The UDP socket this instance uses to send and receive RTCP packets. */ private DatagramSocket controlSocket; /** * RTP packet input stream used by RTPManager. */ private RTPConnectorInputStream dataInputStream; /** * RTP packet output stream used by RTPManager. */ private RTPConnectorOutputStream dataOutputStream; /** * The UDP socket this instance uses to send and receive RTP packets. */ private DatagramSocket dataSocket; /** * Initializes a new RTPConnectorImpl which is to use a given pair * of datagram sockets for RTP and RTCP traffic specified in the form of a * StreamConnector. * * @param connector the pair of datagram sockets for RTP and RTCP traffic * the new instance is to use */ public RTPConnectorImpl(StreamConnector connector) { if (connector == null) throw new NullPointerException("connector"); this.connector = connector; } /** * Add a stream target. A stream target is the destination address which * this RTP session will send its data to. For a single session, we can add * multiple SessionAddresses, and for each address, one copy of data will be * sent to. * * @param target Destination target address * @throws IOException if there was a socket-related error while adding the * specified target */ public void addTarget(SessionAddress target) throws IOException { getControlOutputStream() .addTarget( target.getControlAddress(), target.getControlPort()); getDataOutputStream() .addTarget( target.getDataAddress(), target.getDataPort()); } /** * Closes all sockets, stream, and the StreamConnector that this * RTPConnector is using. */ public void close() { if (dataOutputStream != null) { dataOutputStream.close(); dataOutputStream = null; } if (controlOutputStream != null) { controlOutputStream.close(); controlOutputStream = null; } if (dataInputStream != null) { dataInputStream.close(); dataInputStream = null; } if (controlInputStream != null) { controlInputStream.close(); controlInputStream = null; } connector.close(); } /** * Creates the RTCP packet input stream to be used by RTPManager. * * @return a new RTCP packet input stream to be used by RTPManager * @throws IOException if an error occurs during the creation of the RTCP * packet input stream */ protected RTPConnectorInputStream createControlInputStream() throws IOException { return new RTCPConnectorInputStream(getControlSocket()); } /** * Creates the RTCP packet output stream to be used by RTPManager. * * @return a new RTCP packet output stream to be used by RTPManager * @throws IOException if an error occurs during the creation of the RTCP * packet output stream */ protected RTPConnectorOutputStream createControlOutputStream() throws IOException { return new RTPConnectorOutputStream(getControlSocket()); } /** * Creates the RTP packet input stream to be used by RTPManager. * * @return a new RTP packet input stream to be used by RTPManager * @throws IOException if an error occurs during the creation of the RTP * packet input stream */ protected RTPConnectorInputStream createDataInputStream() throws IOException { return new RTPConnectorInputStream(getDataSocket()); } /** * Creates the RTP packet output stream to be used by RTPManager. * * @return a new RTP packet output stream to be used by RTPManager * @throws IOException if an error occurs during the creation of the RTP * packet output stream */ protected RTPConnectorOutputStream createDataOutputStream() throws IOException { return new RTPConnectorOutputStream(getDataSocket()); } /** * Gets the StreamConnector which represents the pair of datagram * sockets for RTP and RTCP traffic used by this instance. * * @return the StreamConnector which represents the pair of * datagram sockets for RTP and RTCP traffic used by this instance */ public final StreamConnector getConnector() { return connector; } /** * Returns the input stream that is handling incoming RTCP packets. * * @return the input stream that is handling incoming RTCP packets. * * @throws IOException if an error occurs during the creation of the RTCP * packet input stream */ public RTPConnectorInputStream getControlInputStream() throws IOException { return getControlInputStream(true); } /** * Gets the PushSourceStream which gives access to the RTCP data * received from the remote targets and optionally creates it if it does not * exist yet. * * @param create true to create the PushSourceStream which * gives access to the RTCP data received from the remote targets if it does * not exist yet; otherwise, false * @return the PushBufferStream which gives access to the RTCP data * received from the remote targets; null if it does not exist yet * and create is false * @throws IOException if creating the PushSourceStream fails */ protected RTPConnectorInputStream getControlInputStream(boolean create) throws IOException { if ((controlInputStream == null) && create) controlInputStream = createControlInputStream(); return controlInputStream; } /** * Returns the input stream that is handling outgoing RTCP packets. * * @return the input stream that is handling outgoing RTCP packets. * * @throws IOException if an error occurs during the creation of the RTCP * packet output stream */ public RTPConnectorOutputStream getControlOutputStream() throws IOException { return getControlOutputStream(true); } /** * Gets the OutputDataStream which is used to write RTCP data to be * sent to from the remote targets and optionally creates it if it does not * exist yet. * * @param create true to create the OutputDataStream which * is to be used to write RTCP data to be sent to the remote targets if it * does not exist yet; otherwise, false * @return the OutputDataStream which is used to write RTCP data to * be sent to the remote targets; null if it does not exist yet and * create is false * @throws IOException if creating the OutputDataStream fails */ protected RTPConnectorOutputStream getControlOutputStream(boolean create) throws IOException { if ((controlOutputStream == null) && create) controlOutputStream = createControlOutputStream(); return controlOutputStream; } /** * Gets the UDP Socket this instance uses to send and receive RTCP packets. * * @return the UDP Socket this instance uses to send and receive RTCP * packets */ public DatagramSocket getControlSocket() { if (controlSocket == null) controlSocket = connector.getControlSocket(); return controlSocket; } /** * Returns the input stream that is handling incoming RTP packets. * * @return the input stream that is handling incoming RTP packets. * * @throws IOException if an error occurs during the creation of the RTP * packet input stream */ public RTPConnectorInputStream getDataInputStream() throws IOException { return getDataInputStream(true); } /** * Gets the PushSourceStream which gives access to the RTP data * received from the remote targets and optionally creates it if it does not * exist yet. * * @param create true to create the PushSourceStream which * gives access to the RTP data received from the remote targets if it does * not exist yet; otherwise, false * @return the PushBufferStream which gives access to the RTP data * received from the remote targets; null if it does not exist yet * and create is false * @throws IOException if creating the PushSourceStream fails */ protected RTPConnectorInputStream getDataInputStream(boolean create) throws IOException { if ((dataInputStream == null) && create) dataInputStream = createDataInputStream(); return dataInputStream; } /** * Returns the input stream that is handling outgoing RTP packets. * * @return the input stream that is handling outgoing RTP packets. * * @throws IOException if an error occurs during the creation of the RTP */ public RTPConnectorOutputStream getDataOutputStream() throws IOException { return getDataOutputStream(true); } /** * Gets the OutputDataStream which is used to write RTP data to be * sent to from the remote targets and optionally creates it if it does not * exist yet. * * @param create true to create the OutputDataStream which * is to be used to write RTP data to be sent to the remote targets if it * does not exist yet; otherwise, false * @return the OutputDataStream which is used to write RTP data to * be sent to the remote targets; null if it does not exist yet and * create is false * @throws IOException if creating the OutputDataStream fails */ public RTPConnectorOutputStream getDataOutputStream(boolean create) throws IOException { if ((dataOutputStream == null) && create) dataOutputStream = createDataOutputStream(); return dataOutputStream; } /** * Gets the UDP socket this instance uses to send and receive RTP packets. * * @return the UDP socket this instance uses to send and receive RTP packets */ public DatagramSocket getDataSocket() { if (dataSocket == null) dataSocket = connector.getDataSocket(); return dataSocket; } /** * Provides a dummy implementation to {@link * RTPConnector#getReceiveBufferSize()} that always returns -1. */ public int getReceiveBufferSize() { // Not applicable return -1; } /** * Provides a dummy implementation to {@link * RTPConnector#getRTCPBandwidthFraction()} that always returns -1. */ public double getRTCPBandwidthFraction() { // Not applicable return -1; } /** * Provides a dummy implementation to {@link * RTPConnector#getRTCPSenderBandwidthFraction()} that always returns * -1. */ public double getRTCPSenderBandwidthFraction() { // Not applicable return -1; } /** * Provides a dummy implementation to {@link * RTPConnector#getSendBufferSize()} that always returns -1. */ public int getSendBufferSize() { // Not applicable return -1; } /** * Removes a target from our session. If a target is removed, there will be * no data sent to that address. * * @param target Destination target to be removed */ public void removeTarget(SessionAddress target) { if (controlOutputStream != null) controlOutputStream .removeTarget( target.getControlAddress(), target.getControlPort()); if (dataOutputStream != null) dataOutputStream .removeTarget( target.getDataAddress(), target.getDataPort()); } /** * Remove all stream targets. After this operation is done. There will be * no targets receiving data, so no data will be sent. */ public void removeTargets() { if (controlOutputStream != null) controlOutputStream.removeTargets(); if (dataOutputStream != null) dataOutputStream.removeTargets(); } /** * Provides a dummy implementation to {@link * RTPConnector#setReceiveBufferSize(int)}. * * @param size ignored. */ public void setReceiveBufferSize(int size) throws IOException { // Nothing should be done here :-) } /** * Provides a dummy implementation to {@link * RTPConnector#setSendBufferSize(int)}. * * @param size ignored. */ public void setSendBufferSize(int size) throws IOException { // Nothing should be done here :-) } }