blob: eb12988b21a56e4cfe0a54b617fb2bc5ae7e0c71 [file] [log] [blame]
// Copyright (C) 2001,2002,2003,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 sources.h
*
* @short Sources of synchronization and participants related clases.
**/
#ifndef CCXX_RTP_SOURCES_H_
#define CCXX_RTP_SOURCES_H_
#include <string>
#include <ccrtp/rtcppkt.h>
NAMESPACE_COMMONCPP
/**
* @defgroup sources Participants and synchronization sources.
* @{
**/
/**
* @class SDESItemsHolder
*
* Holds the SDES items and related information from a participant in
* an RTP application. This is a base class for participant classes.
*
* @author Federico Montesino Pouzols <fedemp@altern.org>
**/
class __EXPORT SDESItemsHolder
{
public:
const std::string&
getItem(SDESItemType type) const;
inline const std::string&
getPRIVPrefix() const
{ return sdesItems[SDESItemTypeEND]; }
void
setItem(SDESItemType item, const std::string& val);
inline void
setPRIVPrefix(const std::string& val)
{ sdesItems[SDESItemTypeEND] = val; }
protected:
SDESItemsHolder()
{ }
inline virtual ~SDESItemsHolder()
{ }
private:
// SDES items for a participant.
// sdesItems[0] (== sdesItems[SDESItemTypeEND]) holds the prefix
// value for the PRIV item. The rest of entries hold the
// correponding SDES item value.
std::string sdesItems[SDESItemTypeLast + 1];
};
/**
* @class Participant
* @short A class of objects representing remote participants (RTP
* applications) in a multimedia session.
*
* Any RTP socket/queue class that directly or indirectly inherits
* from QueueRTCPManager (and hence has RTCP support) will represent
* participants from which any RTP or RTCP packet has been received
* through a Participant object. These Participant objects are
* entities such as end systems (user applications, monitors, etc),
* RTP mixers and RTP translators.
*
* Participant objects are identified by a CNAME and provide access to
* all known data about the source of RTP/RTCP packets, such as the
* CNAME and any other SDES item. Each participant object is related
* to one or more synchronization objects (@see SyncSource).
*
* If an RTP application based on ccRTP receives packets from itself
* (for instance, it is included in the destination list), there will
* be a Participant object that corresponds to the "local participant"
* (RTPApplication) object.
*
* @author Federico Montesino Pouzols <fedemp@altern.org>
*
* @todo implement reference counting from sources, so that when a
* source is destroyed, we know if the Participant should be
* destroyed.
**/
class __EXPORT Participant : private SDESItemsHolder
{
public:
/**
* Get the value of an SDES item. For instance,
* getSDESItem(SDESItemTypeCNAME), return the CNAME of this
* Participant.
*
* @param type type of SDES item to get value of.
*
* @return value of the SDES item as a string.
* @retval empty string when the value is not known (no RTCP
* packet with the requested SDES item has been received from this
* source).
**/
const std::string&
getSDESItem(SDESItemType type) const
{ return SDESItemsHolder::getItem(type); }
/**
* Get the prefix value for the PRIV SDES item.
*
* @return PRIV SDES item prefix as a string.
* @retval empty string when no PRIV SDES item has been
* received from this source.
**/
inline const std::string&
getPRIVPrefix() const
{ return SDESItemsHolder::getPRIVPrefix(); }
/**
* Construct a new participant.
*
* @param cname Unique CNAME identifier.
**/
Participant(const std::string& cname);
~Participant();
private:
friend class ParticipantHandler;
/**
* Set the value of a SDES item.
**/
inline void
setSDESItem(SDESItemType item, const std::string& val)
{ SDESItemsHolder::setItem(item,val); }
/**
* Set prefix value for the PRIV SDES item.
**/
inline void
setPRIVPrefix(const std::string val)
{ SDESItemsHolder::setPRIVPrefix(val); }
};
/**
* @class SyncSource
* @short Synchronization source in an RTP session
*
* Each synchronization source in an RTP session is identified by a
* 32-bit numeric SSRC identifier. Each SyncSource object is related
* to a Participant object, which can be retrieved through the
* getParticipant() method.
*
* @author Federico Montesino Pouzols <fedemp@altern.org>
**/
class __EXPORT SyncSource
{
public:
/**
* @enum State
*
* @short Synchronization source states during an RTP session.
*
* In general, new synchronization sources are not considered
* valid until multiple valid data packets or a valid RTCP
* compound packet has been received from the new source (@see
* IncomingDataQueue::setMinValidPacketSequence()). Thus, the
* source will probably be in statePrevalid before reaching
* one of the two states that indicate a valid source:
* stateActive and stateInactive.
*
* A valid participant is in stateActive state if RTP and/or
* RTCP packets are currently being received from it. If,
* after a small number of RTCP report intervals (see
* IncomingDataQueue::setSourceExpirationPeriod() ), no
* packets are received, it will reach the stateInactive
* state. If, after a small number of RTCP report intervals,
* no packet is received from an inactive source, it will be
* deleted.
*
* If RTCP is being used, after receiving a BYE RTCP packet
* from a synchronization source, it will reach the
* stateLeaving state and will be deleted after a delay (see
* QueueRTCPManager::setLeavingDelay()).
*
* Sources in statePrevalid and stateLeaving are not counted
* for the number of session members estimation.
**/
typedef enum {
stateUnknown, ///< No valid packet has been received.
statePrevalid, ///< Some packets have been
///received, but source validity not
///yet guaranteed.
stateActive, ///< We currently receive packets
///(data or control) from this source.
stateInactive, ///< Was active in the near past but
///no packet from this source has
///been received lately.
stateLeaving ///< An RTCP BYE has been received
///from the source.
} State;
/**
* @param ssrc SSRC identifier of the source, unique in each
* session.
*/
SyncSource(uint32 ssrc);
~SyncSource();
State
getState() const
{ return state; }
/**
* Whether this source sends RTP data packets.
**/
bool isSender() const
{ return activeSender; }
uint32 getID() const
{ return SSRC; }
/**
* Get the participant this synchronization source is
* asociated to.
*
* @retval NULL if the stack has not been yet able to identify
* the participant this source is associated to.
**/
inline Participant*
getParticipant() const
{ return participant; }
tpport_t getDataTransportPort() const
{ return dataTransportPort; }
tpport_t getControlTransportPort() const
{ return controlTransportPort; }
const InetAddress& getNetworkAddress() const
{ return networkAddress; }
protected:
/**
* @param source The RTPSource object being copied
*/
SyncSource(const SyncSource& source);
SyncSource&
operator=(const SyncSource& source);
private:
friend class SyncSourceHandler;
inline void
setState(State st)
{ state = st; }
/**
* Mark this source as an active sender.
**/
inline void
setSender(bool active)
{ activeSender = active; }
inline void
setParticipant(Participant& p)
{ participant = &p; }
void setDataTransportPort(tpport_t p)
{ dataTransportPort = p; }
void setControlTransportPort(tpport_t p)
{ controlTransportPort = p; }
void setNetworkAddress(InetAddress addr)
{ networkAddress = addr; }
inline void
setLink(void *l)
{ link = l; }
void *getLink() const
{ return link; }
// validity state of this source
State state;
// 32-bit SSRC identifier.
uint32 SSRC;
// A valid source not always is active
bool activeSender;
// The corresponding participant.
Participant* participant;
// Network protocol address for data and control connection
// (both are assumed to be the same).
InetAddress networkAddress;
tpport_t dataTransportPort;
tpport_t controlTransportPort;
// Pointer to the SyncSourceLink or similar object in the
// service queue. Saves a lot of searches in the membership
// table.
void* link;
};
/**
* @class RTPApplication
* @short An RTP application, holding identifying RTCP SDES item
* values. Represents local participants.
*
* An application in the context of RTP: an entity that has a CNAME
* (unique identifier in the form of user\@host.domain) as well as
* other RTCP SDES items (such as NAME or TOOL), and may open a number
* of RTP sessions. Each application is a different source of
* synchronization (with a potentially diferent SSRC identifier) in
* each RTP session it participates. All the sources of
* synchronization from a participant are tied together by means of
* the CNAME.
*
* The definition of this class allows applications based on ccRTP to
* implement several "RTP applications" in the same process. Each
* object of this class represents a local participant.
*
* @author Federico Montesino Pouzols <fedemp@altern.org>
**/
class __EXPORT RTPApplication : private SDESItemsHolder
{
private:
struct ParticipantLink;
public:
/**
* Create a new RTP application. If the CNAME string provided
* has zero length, it is guessed from the user and machine
* name.
*
* @param cname Local participant canonical name.
**/
RTPApplication(const std::string& cname);
~RTPApplication();
inline void
setSDESItem(SDESItemType item, const std::string& val)
{ SDESItemsHolder::setItem(item,val); }
inline void
setPRIVPrefix(const std::string& val)
{ SDESItemsHolder::setPRIVPrefix(val); }
const std::string&
getSDESItem(SDESItemType item) const
{ return SDESItemsHolder::getItem(item); }
inline const std::string&
getPRIVPrefix() const
{ return SDESItemsHolder::getPRIVPrefix(); }
/**
* Iterator through the list of participants in this
* session. Somehow resembles and standard const_iterator
**/
class ParticipantsIterator
{
public:
typedef std::forward_iterator_tag iterator_category;
typedef Participant value_type;
typedef std::ptrdiff_t difference_type;
typedef const Participant* pointer;
typedef const Participant& reference;
ParticipantsIterator(ParticipantLink* p = NULL) :
link(p)
{ }
ParticipantsIterator(const ParticipantsIterator& pi) :
link(pi.link)
{ }
reference operator*() const
{ return *(link->getParticipant()); }
pointer operator->() const
{ return link->getParticipant(); }
ParticipantsIterator& operator++() {
link = link->getNext();
return *this;
}
ParticipantsIterator operator++(int) {
ParticipantsIterator result(*this);
++(*this);
return result;
}
friend bool operator==(const ParticipantsIterator& l,
const ParticipantsIterator& r)
{ return l.link == r.link; }
friend bool operator!=(const ParticipantsIterator& l,
const ParticipantsIterator& r)
{ return l.link != r.link; }
private:
ParticipantLink *link;
};
ParticipantsIterator begin()
{ return ParticipantsIterator(firstPart); }
ParticipantsIterator end()
{ return ParticipantsIterator(NULL); }
const Participant*
getParticipant(const std::string& cname) const;
private:
friend class ApplicationHandler;
struct ParticipantLink {
ParticipantLink(Participant& p,
ParticipantLink* l) :
participant(&p), next(l)
{ }
inline ~ParticipantLink() { delete participant; }
inline Participant* getParticipant() { return participant; }
inline ParticipantLink* getPrev() { return prev; }
inline ParticipantLink* getNext() { return next; }
inline void setPrev(ParticipantLink* l) { prev = l; }
inline void setNext(ParticipantLink* l) { next = l; }
Participant* participant;
ParticipantLink* next, *prev;
};
void
addParticipant(Participant& part);
void
removeParticipant(ParticipantLink* part);
/**
* Find out the local CNAME as user\@host and store it as part
* of the internal state of this class.
*/
void
findCNAME();
/// Hash table with sources of RTP and RTCP packets.
static const size_t defaultParticipantsNum;
Participant** participants;
/// List of participants, ordered from older to newer.
ParticipantLink* firstPart, * lastPart;
};
/**
* Get the RTPApplication object for the "default" application (the
* only one used by common applications -those that only implement one
* "RTP application"). Note that this application object differs from
* all the others that may be defined in that it is automatically
* constructed by the ccRTP stack and its CNAME is automatically
* assigned (as user\@host), whereas the other application objects'
* CNAME is provided to its constructor.
**/
__EXPORT RTPApplication& defaultApplication();
/** @}*/ // sources
END_NAMESPACE
#endif //CCXX_RTP_SOURCES_H_
/** EMACS **
* Local variables:
* mode: c++
* c-basic-offset: 8
* End:
*/