// 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:
 */
