/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jitsi.impl.neomedia; import java.io.*; import java.net.*; import javax.media.rtp.*; import org.jitsi.service.neomedia.*; /** * Provides a base/default implementation of <tt>RTPConnector</tt> which has * factory methods for its control and data input and output streams and has an * associated <tt>StreamConnector</tt>. * * @author Bing SU (nova.su@gmail.com) * @author Lyubomir Marinov */ public abstract class AbstractRTPConnector implements RTPConnector { /** * The pair of datagram sockets for RTP and RTCP traffic that this instance * uses in the form of a <tt>StreamConnector</tt>. */ protected final StreamConnector connector; /** * RTCP packet input stream used by <tt>RTPManager</tt>. */ private RTPConnectorInputStream controlInputStream; /** * RTCP packet output stream used by <tt>RTPManager</tt>. */ private RTPConnectorOutputStream controlOutputStream; /** * RTP packet input stream used by <tt>RTPManager</tt>. */ private RTPConnectorInputStream dataInputStream; /** * RTP packet output stream used by <tt>RTPManager</tt>. */ private RTPConnectorOutputStream dataOutputStream; /** * Initializes a new <tt>AbstractRTPConnector</tt> which is to use a given * pair of datagram sockets for RTP and RTCP traffic specified in the form * of a <tt>StreamConnector</tt>. * * @param connector the pair of datagram sockets for RTP and RTCP traffic * the new instance is to use */ public AbstractRTPConnector(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 { InetAddress controlAddress = target.getControlAddress(); if (controlAddress != null) { getControlOutputStream().addTarget( controlAddress, target.getControlPort()); } getDataOutputStream().addTarget( target.getDataAddress(), target.getDataPort()); } /** * Closes all sockets, stream, and the <tt>StreamConnector</tt> that this * <tt>RTPConnector</tt> 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 <tt>RTPManager</tt>. * * @return a new RTCP packet input stream to be used by <tt>RTPManager</tt> * @throws IOException if an error occurs during the creation of the RTCP * packet input stream */ protected abstract RTPConnectorInputStream createControlInputStream() throws IOException; /** * Creates the RTCP packet output stream to be used by <tt>RTPManager</tt>. * * @return a new RTCP packet output stream to be used by <tt>RTPManager</tt> * @throws IOException if an error occurs during the creation of the RTCP * packet output stream */ protected abstract RTPConnectorOutputStream createControlOutputStream() throws IOException; /** * Creates the RTP packet input stream to be used by <tt>RTPManager</tt>. * * @return a new RTP packet input stream to be used by <tt>RTPManager</tt> * @throws IOException if an error occurs during the creation of the RTP * packet input stream */ protected abstract RTPConnectorInputStream createDataInputStream() throws IOException; /** * Creates the RTP packet output stream to be used by <tt>RTPManager</tt>. * * @return a new RTP packet output stream to be used by <tt>RTPManager</tt> * @throws IOException if an error occurs during the creation of the RTP * packet output stream */ protected abstract RTPConnectorOutputStream createDataOutputStream() throws IOException; /** * Gets the <tt>StreamConnector</tt> which represents the pair of datagram * sockets for RTP and RTCP traffic used by this instance. * * @return the <tt>StreamConnector</tt> 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 <tt>PushSourceStream</tt> which gives access to the RTCP data * received from the remote targets and optionally creates it if it does not * exist yet. * * @param create <tt>true</tt> to create the <tt>PushSourceStream</tt> which * gives access to the RTCP data received from the remote targets if it does * not exist yet; otherwise, <tt>false</tt> * @return the <tt>PushBufferStream</tt> which gives access to the RTCP data * received from the remote targets; <tt>null</tt> if it does not exist yet * and <tt>create</tt> is <tt>false</tt> * @throws IOException if creating the <tt>PushSourceStream</tt> 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 <tt>OutputDataStream</tt> 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 <tt>true</tt> to create the <tt>OutputDataStream</tt> which * is to be used to write RTCP data to be sent to the remote targets if it * does not exist yet; otherwise, <tt>false</tt> * @return the <tt>OutputDataStream</tt> which is used to write RTCP data to * be sent to the remote targets; <tt>null</tt> if it does not exist yet and * <tt>create</tt> is <tt>false</tt> * @throws IOException if creating the <tt>OutputDataStream</tt> fails */ protected RTPConnectorOutputStream getControlOutputStream(boolean create) throws IOException { if ((controlOutputStream == null) && create) controlOutputStream = createControlOutputStream(); return controlOutputStream; } /** * 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 <tt>PushSourceStream</tt> which gives access to the RTP data * received from the remote targets and optionally creates it if it does not * exist yet. * * @param create <tt>true</tt> to create the <tt>PushSourceStream</tt> which * gives access to the RTP data received from the remote targets if it does * not exist yet; otherwise, <tt>false</tt> * @return the <tt>PushBufferStream</tt> which gives access to the RTP data * received from the remote targets; <tt>null</tt> if it does not exist yet * and <tt>create</tt> is <tt>false</tt> * @throws IOException if creating the <tt>PushSourceStream</tt> 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 <tt>OutputDataStream</tt> 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 <tt>true</tt> to create the <tt>OutputDataStream</tt> which * is to be used to write RTP data to be sent to the remote targets if it * does not exist yet; otherwise, <tt>false</tt> * @return the <tt>OutputDataStream</tt> which is used to write RTP data to * be sent to the remote targets; <tt>null</tt> if it does not exist yet and * <tt>create</tt> is <tt>false</tt> * @throws IOException if creating the <tt>OutputDataStream</tt> fails */ public RTPConnectorOutputStream getDataOutputStream(boolean create) throws IOException { if ((dataOutputStream == null) && create) dataOutputStream = createDataOutputStream(); return dataOutputStream; } /** * Provides a dummy implementation to {@link * RTPConnector#getReceiveBufferSize()} that always returns <tt>-1</tt>. */ public int getReceiveBufferSize() { // Not applicable return -1; } /** * Provides a dummy implementation to {@link * RTPConnector#getRTCPBandwidthFraction()} that always returns <tt>-1</tt>. */ public double getRTCPBandwidthFraction() { // Not applicable return -1; } /** * Provides a dummy implementation to {@link * RTPConnector#getRTCPSenderBandwidthFraction()} that always returns * <tt>-1</tt>. */ public double getRTCPSenderBandwidthFraction() { // Not applicable return -1; } /** * Provides a dummy implementation to {@link * RTPConnector#getSendBufferSize()} that always returns <tt>-1</tt>. */ 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 :-) } }