blob: eebd21e41d33b7534a4dbeed56a5d0baff887cd5 [file] [log] [blame]
// Copyright (C) 2001,2002,2004 Federico Montesino Pouzols <fedemp@altern.org>.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
//
// This exception applies only to the code released under the name GNU
// ccRTP. If you copy code from other releases into a copy of GNU
// ccRTP, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for GNU ccRTP, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
//
/**
* @file cqueue.h
*
* @short Generic RTCP control queues.
**/
#ifndef CCXX_RTP_CQUEUE_H_
#define CCXX_RTP_CQUEUE_H_
#include <ccrtp/ioqueue.h>
#ifdef CCXX_NAMESPACES
namespace ost {
#endif
/**
* @defgroup cqueue Generic RTCP control queues.
* @{
**/
/**
* @class QueueRTCPManager
* @short Adds generic management of RTCP functions to an RTP data
* queue.
*
* Extends an RTP data i/o queue adding management of RTCP functions:
*
* Provide feedback on the quality of the data distribution.
*
* Convey the CNAME (persistent transport-level identifier) for every
* RTP source.
*
* Control the sending rate of RTCP packets
*
* Convey minimal control information about the participants
*
* This class implements generic RTCP behaviour (as specified in RFC
* 1889/draft-ietf-avt-rtp-new) and may be specialized for specific
* profiles (see AVPQueue) or particular RTCP extensions.
*
* @author Federico Montesino Pouzols <fedemp@altern.org>
**/
class __EXPORT QueueRTCPManager : public RTPDataQueue,
protected RTCPCompoundHandler
{
public:
/**
* Get the most recent sender report received from a
* synchronization source.
*
* @param src Synchronization source of the sender info.
* @return Most recent sender info received from src.
* @retval NULL when no sender report has been received from
* the specified source.
**/
RTCPSenderInfo* getMRSenderInfo(SyncSource& src);
/**
* Ask for the info in the most recent receiver report about
* the local source received from the source given as
* parameter.
*
* @param srcFrom Source of the receiver info.
* @return most recent receiver info received from src.
* @retval NULL when no receiver report has been received from
* the specified source.
*/
RTCPReceiverInfo* getMRReceiverInfo(SyncSource& srcFrom);
/**
* Set how much time the stack will wait before deleting a
* synchronization source that has sent an RTCP BYE packet.
*
* @param delay delay in microseconds.
*
* @note The default delay is 1000000 microseconds
**/
void setLeavingDelay(microtimeout_t delay)
{ leavingDelay = delay; }
/**
* This method sets the maximum end to end delay allowed. If
* the processing delay plus the trip time for a packet is
* greater than the end to end delay, the packet is discarded,
* and the application cannot get it.
*
* This is a way of setting an upper bound to the end to end
* delay, computed as the elapsed time between the packet
* timestamping at the sender side, and the picking of the
* packet at the receiver side.
*
* @param t maximum end to end delay allowed. A value of 0
* implies there is no limit and is the default
*/
inline void
setEnd2EndDelay(microtimeout_t t)
{ end2EndDelay = t; }
inline microtimeout_t
getDefaultEnd2EndDelay() const
{ return defaultEnd2EndDelay; }
inline microtimeout_t
getEnd2EndDelay() const
{ return end2EndDelay; }
/**
* Specify the fraction of the total control bandwith to be
* dedicated to senders reports.
*
* @param fraction fraction of bandwidth, must be between 0 an 1.
*
* This method sets the fraction of the global control
* bandwidth that will be dedicated to senders reports. Of
* course, <code>1 - fraction</code> will be dedicated to
* receivers reports.
*
* @see setControlBandwidth
*/
inline void
setSendersControlFraction(float fraction)
{ sendControlBwFract = fraction; recvControlBwFract = 1 - fraction;}
/**
* Manually set the minimum interval for sending RTP compound
* packets
*
* @param interval minimum interval between RTCP packets, in
* microseconds.
*
* @see computeRTCPInterval()
**/
void
setMinRTCPInterval(microtimeout_t interval)
{ rtcpMinInterval = interval; }
/**
* Get the total number of RTCP packets sent until now
**/
inline uint32
getSendRTCPPacketCount() const
{ return ctrlSendCount; }
protected:
QueueRTCPManager(uint32 size = RTPDataQueue::defaultMembersHashSize,
RTPApplication& app = defaultApplication());
QueueRTCPManager(uint32 ssrc,
uint32 size = RTPDataQueue::defaultMembersHashSize,
RTPApplication& app = defaultApplication());
virtual
~QueueRTCPManager();
const RTPApplication&
getApplication()
{ return queueApplication; }
inline void
setControlBandwidth(float fraction)
{ controlBwFract = fraction; }
float
getControlBandwidth() const
{ return controlBwFract; }
/**
* Build and send RTCP packets following timing rules
* (including the "timer reconsideration" algorithm).
**/
void
controlTransmissionService();
/**
* Process incoming RTCP packets pending in the control
* reception socket.
**/
void
controlReceptionService();
/**
* Appy collision and loop detection and correction algorithm
* when receiving RTCP packets. Follows section 8.2 in
* draft-ietf-avp-rtp-new.
*
* @param sourceLink link to the source object.
* @param is_new whether the source has been just recorded.
* @param na RTCP packet network address.
* @param tp RTCP packet source transport port.
*
* @return whether the packet must not be discarded.
**/
bool checkSSRCInRTCPPkt(SyncSourceLink& sourceLink, bool is_new,
InetAddress& na, tpport_t tp);
void
endQueueRTCPManager();
/**
* Plug-in for processing (acquire information carried in) an
* incoming RTCP Sender Report. The default implementation in
* this class only processes the sender information and the
* receiver report blocks about the local source.
*
* @param source Synchronization source this report comes from.
* @param SR Sender report structure.
* @param blocks Number of report blocks in the packet.
**/
virtual void
onGotSR(SyncSource& source, SendReport& SR, uint8 blocks);
/**
* Plug-in for processing (acquire information carried in) an
* incoming RTCP Receiver Report. The default implementation
* in this class only processes the receiver report blocks
* about the local source.
*
* @param source Synchronization source this report comes from.
* @param RR Receiver report structure
* @param blocks Number of report blocks in the packet
**/
virtual void
onGotRR(SyncSource& source, RecvReport& RR, uint8 blocks);
/**
* @param source Synchronization source of SDES RTCP packet.
* @param pkt SDES RTCP packet received.
**/
bool
onGotSDES(SyncSource& source, RTCPPacket& pkt);
/**
* Plug-in for handling of SDES chunks.
*
* @param source Synchronization source of SDES chunk.
* @param chunk SDES chunk structure.
* @param len Length of chunk, in octets.
*
* @return whether there was a CNAME.
**/
virtual bool
onGotSDESChunk(SyncSource& source, SDESChunk& chunk, size_t len);
/**
* Plug-in for handling of APP (application specific) RTCP
* packets.
*
* @param - Synchronization source of this packet.
* @param - RTCP APP packet struct.
* @param - Length of the app data packet, including ssrc.
* name and app. specific data.
**/
inline virtual void
onGotAPP(SyncSource&, RTCPCompoundHandler::APPPacket&,
size_t)
{ return; }
inline timeval
getRTCPCheckInterval()
{ return rtcpCheckInterval; }
/**
* Get the number of data packets sent at the time the last SR
* was generated.
**/
uint32
getLastSendPacketCount() const
{ return lastSendPacketCount; }
/**
* @param n Number of members.
**/
inline void
setPrevMembersNum(uint32 n)
{ reconsInfo.rtcpPMembers = n; }
inline uint32
getPrevMembersCount() const
{ return reconsInfo.rtcpPMembers; }
/**
* This method is used to send an RTCP BYE packet. An RTCP
* BYE packet is sent when one of the the following
* circumstances occur:
* - when leaving the session
* - when we have detected that another synchronization source
* in the same session is using the same SSRC identifier as
* us.
*
* Try to post a BYE message. It will send a BYE packet as
* long as at least one RTP or RTCP packet has been sent
* before. If the number of members in the session is more
* than 50, the algorithm described in section 6.3.7 of
* RFC 3550 is applied in order to avoid a flood
* of BYE messages.
*
* @param reason reason to specify in the BYE packet.
**/
size_t
dispatchBYE(const std::string& reason);
size_t
sendControlToDestinations(unsigned char* buffer, size_t len);
private:
QueueRTCPManager(const QueueRTCPManager &o);
QueueRTCPManager&
operator=(const QueueRTCPManager &o);
/**
* Posting of RTCP messages.
*
* @return std::size_t number of octets sent
*/
size_t
dispatchControlPacket();
/**
* For picking up incoming RTCP packets if they are waiting. A
* timeout for the maximum interval since the last RTCP packet
* had been received is also returned. This is checked every
* rtcpCheckInterval seconds.
*
* This method decomposes all incoming RTCP compound packets
* pending in the control socket and processes each RTCP
* packet.
*
**/
void
takeInControlPacket();
/**
* Computes the interval for sending RTCP compound packets,
* based on the average size of RTCP packets sent and
* received, and the current estimated number of participants
* in the session.
*
* @note This currently follows the rules in section 6 of
* RFC 3550
* @todo make it more flexible as recommended in the draft. For now,
* we have setMinRTCPInterval.
*
* @return interval for sending RTCP compound packets
**/
virtual timeval
computeRTCPInterval();
/**
* Choose which should be the type of the next SDES item
* sent. This method is called when packing SDES chunks in a
* new RTCP packet.
*
* @return type of the next SDES item to be sent
**/
virtual SDESItemType
scheduleSDESItem();
/**
* Plug-in for SSRC collision handling.
*
* @param - previously identified source.
**/
inline virtual void
onSSRCCollision(const SyncSource&)
{ }
/**
* Virtual reimplemented from RTPDataQueue
**/
virtual bool
end2EndDelayed(IncomingRTPPktLink& p);
/**
* Plug-in for processing of SR/RR RTCP packet
* profile-specific extensions (third part of SR reports or
* second part of RR reports).
*
* @param - Content of the profile extension.
* @param - Length of the extension, in octets.
**/
inline virtual void
onGotRRSRExtension(unsigned char*, size_t)
{ return; }
/**
* A plugin point for goodbye message. Called when a BYE RTCP
* packet has been received from a valid synchronization
* source.
*
* @param - synchronization source from what a BYE RTCP
* packet has been just received.
* @param - reason string the source has provided.
**/
inline virtual void
onGotGoodbye(const SyncSource&, const std::string&)
{ return; }
/**
* Process a BYE packet just received and identified.
*
* @param pkt previously identified RTCP BYE packet
* @param pointer octet number in the RTCP reception buffer
* where the packet is stored
* @param len total length of the compount RTCP packet the BYE
* packet to process is contained
*
* @bug if the bye packet contains several SSRCs,
* eventSourceLeaving is only called for the last one
**/
bool
getBYE(RTCPPacket &pkt, size_t &pointer, size_t len);
/**
* @return number of Report Blocks packed
**/
uint8
packReportBlocks(RRBlock* blocks, uint16& len, uint16& available);
/**
* Builds an SDES RTCP packet. Each chunk is built following
* appendix A.4 in draft-ietf-avt-rtp-new.
*
* @param len provisionary length of the RTCP compound packet
*
* @return
**/
void
packSDES(uint16& len);
/**
* This must be called in order to update the average RTCP compound
* packet size estimation when:
*
* a compoung RTCP packet is received (6.3.3).
*
* a compound RTCP packet is transmitted (6.3.6).
*
* @param len length in octets of the compound RTCP packet
* just received/transmitted.
**/
void
updateAvgRTCPSize(size_t len);
/**
* Apply reverse reconsideration adjustment to timing
* parameters when receiving BYE packets and not waiting to
* send a BYE.
**/
void
reverseReconsideration();
bool
timerReconsideration();
/**
* Purge sources that do not seem active any more.
*
* @note MUST be perform at least every RTCP transmission
* interval
* @todo implement it. It may be dangerous and anyway should
* be optional.
**/
void
expireSSRCs();
/**
* To be executed when whe are leaving the session.
**/
void
getOnlyBye();
/**
* Set item value from a string without null termination (as
* it is transported in RTCP packets).
**/
void
setSDESItem(Participant* part, SDESItemType type,
const char* const value, size_t len);
/**
* Set PRIV item previx value from a string without null
* termination (as it is transported in RTCP packets).
**/
void
setPRIVPrefix(Participant* part, const char* const value, size_t len);
/**
* For certain control calculations in RTCP, the size of the
* underlying network and transport protocols is needed. This
* method provides the size of the network level header for
* the default case of IP (20 octets). In case other protocol
* with different header size is used, this method should be
* redefined in a new specialized class.
*
* @return size of the headers of the network level. IP (20) by
* default.
**/
inline virtual uint16
networkHeaderSize()
{ return 20; }
/**
* For certain control calculations in RTCP, the size of the
* underlying network and transport protocols is needed. This
* method provides the size of the transport level header for
* the default case of UDP (8 octets). In case other protocol
* with different header size is used, this method should be
* redefined in a new specialized class.
*
* return size of the headers of the transport level. UDP (8)
* by default
**/
inline virtual uint16
transportHeaderSize()
{ return 8; }
SDESItemType
nextSDESType(SDESItemType t);
virtual size_t
sendControl(const unsigned char* const buffer, size_t len) = 0;
virtual size_t
recvControl(unsigned char* buffer, size_t len,
InetHostAddress& na, tpport_t& tp) = 0;
virtual bool
isPendingControl(microtimeout_t timeout) = 0;
// whether the RTCP service is active
volatile bool controlServiceActive;
float controlBwFract, sendControlBwFract, recvControlBwFract;
// number of RTCP packets sent since the beginning
uint32 ctrlSendCount;
// Network + transport headers size, typically size of IP +
// UDP headers
uint16 lowerHeadersSize;
SDESItemType nextScheduledSDESItem;
static const SDESItemType firstSchedulable;
static const SDESItemType lastSchedulable;
// state for rtcp timing. Its meaning is defined in
// draft-ietf-avt-rtp-new, 6.3.
// Parameters for timer reconsideration algorithm
struct {
timeval rtcpTp, rtcpTc, rtcpTn;
uint32 rtcpPMembers;
} reconsInfo;
bool rtcpWeSent;
uint16 rtcpAvgSize;
bool rtcpInitial;
// last time we checked if there were incoming RTCP packets
timeval rtcpLastCheck;
// interval to check if there are incoming RTCP packets
timeval rtcpCheckInterval;
// next time to check if there are incoming RTCP packets
timeval rtcpNextCheck;
// number of RTP data packets sent at the time of the last
// RTCP packet transmission.
uint32 lastSendPacketCount;
// minimum interval for transmission of RTCP packets. The
// result of computeRTCPInterval will always be >= (times a
// random number between 0.5 and 1.5).
microtimeout_t rtcpMinInterval;
microtimeout_t leavingDelay;
static const microtimeout_t defaultEnd2EndDelay;
// Maximum delay allowed between packet timestamping and
// packet availability for the application.
microtimeout_t end2EndDelay;
// Application this queue is bound to.
RTPApplication& queueApplication;
// an empty RTPData
static const uint16 TIMEOUT_MULTIPLIER;
static const double RECONSIDERATION_COMPENSATION;
};
/**
* This class, an RTP/RTCP queue, adds audio/video profile (AVP)
* specific methods to the generic RTCP service queue
* (QueueRTCPManager).
*
* @author Federico Montesino Pouzols <fedemp@altern.org>
**/
class AVPQueue : public QueueRTCPManager
{
public:
/**
* Specify the bandwith available for control (RTCP) packets.
* This method sets the global control bandwidth for both
* sender and receiver reports. As recommended in RFC 1890,
* 1/4 of the total control bandwidth is dedicated to senders,
* whereas 3/4 are dedicated to receivers.
*
* @param fraction fraction of the session bandwidth, between
* 0 and 1
*
* @note If this method is not called, it is assumed that the
* control bandwidth is equal to 5% of the session
* bandwidth. Note also that the RFC RECOMMENDS the 5%.
*
**/
inline void
setControlBandwidth(float fraction)
{ QueueRTCPManager::setControlBandwidth(fraction); }
float
getControlBandwidth() const
{ return QueueRTCPManager::getControlBandwidth(); }
protected:
AVPQueue(uint32 size = RTPDataQueue::defaultMembersHashSize,
RTPApplication& app = defaultApplication()) :
QueueRTCPManager(size,app)
{ }
/**
* Local SSRC is given instead of computed by the queue.
**/
AVPQueue(uint32 ssrc, uint32 size =
RTPDataQueue::defaultMembersHashSize,
RTPApplication& app = defaultApplication()) :
QueueRTCPManager(ssrc,size,app)
{ }
inline virtual ~AVPQueue()
{ }
};
/** @}*/ // cqueue
#ifdef CCXX_NAMESPACES
}
#endif
#endif //CCXX_RTP_CQUEUE_H_
/** EMACS **
* Local variables:
* mode: c++
* c-basic-offset: 8
* End:
*/