// Copyright (C) 2001,2002,2004,2005 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 oqueue.h * * @short Generic RTP output queues. **/ #ifndef CCXX_RTP_OQUEUE_H_ #define CCXX_RTP_OQUEUE_H_ #include <ccrtp/queuebase.h> #include <ccrtp/CryptoContext.h> #include <list> #ifdef CCXX_NAMESPACES namespace ost { #endif /** * @defgroup oqueue Generic RTP output queues. * @{ **/ /** * @class DestinationListHandler * * This class handles a list of destination addresses. Stores network * addresses as InetAddress objects. * * @author Federico Montesino Pouzols <fedemp@altern.org> **/ class __EXPORT DestinationListHandler { protected: struct TransportAddress; std::list<TransportAddress*> destList; public: DestinationListHandler(); ~DestinationListHandler(); /** * Get whether there is only a destination in the list. **/ inline bool isSingleDestination() const { return (1 == destList.size()); } inline TransportAddress* getFirstDestination() const { return destList.front(); } inline void lockDestinationList() const { destinationLock.readLock(); } inline void unlockDestinationList() const { destinationLock.unlock(); } protected: inline void writeLockDestinationList() const { destinationLock.writeLock(); } /** * Locks the object before modifying it. **/ bool addDestinationToList(const InetAddress& ia, tpport_t data, tpport_t control); /** * Locks the object before modifying it. **/ bool removeDestinationFromList(const InetAddress& ia, tpport_t dataPort, tpport_t controlPort); struct TransportAddress { TransportAddress(InetAddress na, tpport_t dtp, tpport_t ctp) : networkAddress(na), dataTransportPort(dtp), controlTransportPort(ctp) { } inline const InetAddress& getNetworkAddress() const { return networkAddress; } inline tpport_t getDataTransportPort() const { return dataTransportPort; } inline tpport_t getControlTransportPort() const { return controlTransportPort; } InetAddress networkAddress; tpport_t dataTransportPort, controlTransportPort; }; private: mutable ThreadLock destinationLock; }; #ifdef CCXX_IPV6 /** * @class DestinationListHandler * * This class handles a list of destination addresses. Stores network * addresses as InetAddress objects. * * @author Federico Montesino Pouzols <fedemp@altern.org> **/ class __EXPORT DestinationListHandlerIPV6 { protected: struct TransportAddressIPV6; std::list<TransportAddressIPV6*> destListIPV6; public: DestinationListHandlerIPV6(); ~DestinationListHandlerIPV6(); /** * Get whether there is only a destination in the list. **/ inline bool isSingleDestinationIPV6() const { return (1 == destListIPV6.size()); } inline TransportAddressIPV6* getFirstDestinationIPV6() const { return destListIPV6.front(); } inline void lockDestinationListIPV6() const { destinationLock.readLock(); } inline void unlockDestinationListIPV6() const { destinationLock.unlock(); } protected: inline void writeLockDestinationListIPV6() const { destinationLock.writeLock(); } /** * Locks the object before modifying it. **/ bool addDestinationToListIPV6(const IPV6Address& ia, tpport_t data, tpport_t control); /** * Locks the object before modifying it. **/ bool removeDestinationFromListIPV6(const IPV6Address& ia, tpport_t dataPort, tpport_t controlPort); struct TransportAddressIPV6 { TransportAddressIPV6(IPV6Address na, tpport_t dtp, tpport_t ctp) : networkAddress(na), dataTransportPort(dtp), controlTransportPort(ctp) { } inline const IPV6Address& getNetworkAddress() const { return networkAddress; } inline tpport_t getDataTransportPort() const { return dataTransportPort; } inline tpport_t getControlTransportPort() const { return controlTransportPort; } IPV6Address networkAddress; tpport_t dataTransportPort, controlTransportPort; }; private: mutable ThreadLock destinationLock; }; #endif /** * @class OutgoingDataQueue * * A generic outgoing RTP data queue supporting multiple destinations. * * @author Federico Montesino Pouzols <fedemp@altern.org> **/ class __EXPORT OutgoingDataQueue: public OutgoingDataQueueBase, #ifdef CCXX_IPV6 protected DestinationListHandlerIPV6, #endif protected DestinationListHandler { public: #ifdef CCXX_IPV6 bool addDestination(const IPV6Address& ia, tpport_t dataPort = DefaultRTPDataPort, tpport_t controlPort = 0); bool forgetDestination(const IPV6Address& ia, tpport_t dataPort = DefaultRTPDataPort, tpport_t controlPort = 0); #endif bool addDestination(const InetHostAddress& ia, tpport_t dataPort = DefaultRTPDataPort, tpport_t controlPort = 0); bool addDestination(const InetMcastAddress& ia, tpport_t dataPort = DefaultRTPDataPort, tpport_t controlPort = 0); bool forgetDestination(const InetHostAddress& ia, tpport_t dataPort = DefaultRTPDataPort, tpport_t controlPort = 0); bool forgetDestination(const InetMcastAddress& ia, tpport_t dataPort = DefaultRTPDataPort, tpport_t controlPort = 0); /** * Add csrc as the CSRC identifier of a new contributor. This * method adds the CSRC identifier to a list of contributors * that will be inserted in every packet enqueued from now on. **/ void addContributor(uint32 csrc); /** * Remove CSRC from the list of contributors. **/ bool removeContributor(uint32 csrc); /** * Determine if outgoing packets are waiting to send. * * @return true if there are packets waiting to be send. */ bool isSending() const; /** * This is used to create a data packet in the send queue. * Sometimes a "NULL" or empty packet will be used instead, and * these are known as "silent" packets. "Silent" packets are * used simply to "push" the scheduler along more accurately * by giving the appearence that a next packet is waiting to * be sent and to provide a valid timestamp for that packet. * * @param stamp Timestamp for expected send time of packet. * @param data Value or NULL if special "silent" packet. * @param len May be 0 to indicate a default by payload type. **/ void putData(uint32 stamp, const unsigned char* data = NULL, size_t len = 0); /** * This is used to create a data packet and send it immediately. * Sometimes a "NULL" or empty packet will be used instead, and * these are known as "silent" packets. "Silent" packets are * used simply to "push" the scheduler along more accurately * by giving the appearence that a next packet is waiting to * be sent and to provide a valid timestamp for that packet. * * @param stamp Timestamp immediate send time of packet. * @param data Value or NULL if special "silent" packet. * @param len May be 0 to indicate a default by payload type. **/ void sendImmediate(uint32 stamp, const unsigned char* data = NULL, size_t len = 0); /** * Set padding. All outgoing packets will be transparently * padded to a multiple of paddinglen. * * @param paddinglen pad packets to a length multiple of paddinglen. **/ void setPadding(uint8 paddinglen) { sendInfo.paddinglen = paddinglen; } /** * Set marker bit for the packet in which the next data * provided will be send. When transmitting audio, should be * set for the first packet of a talk spurt. When transmitting * video, should be set for the last packet for a video frame. * * @param mark Marker bit value for next packet. **/ void setMark(bool mark) { sendInfo.marked = mark; } /** * Get wheter the mark bit will be set in the next packet. **/ inline bool getMark() const { return sendInfo.marked; } /** * Set partial data for an already queued packet. This is often * used for multichannel data. * * @param timestamp Timestamp of packet. * @param data Buffer to copy from. * @param offset Offset to copy from. * @param max Maximum data size. * @return Number of packet data bytes set. **/ size_t setPartial(uint32 timestamp, unsigned char* data, size_t offset, size_t max); inline microtimeout_t getDefaultSchedulingTimeout() const { return defaultSchedulingTimeout; } /** * Set the default scheduling timeout to use when no data * packets are waiting to be sent. * * @param to timeout in milliseconds. **/ inline void setSchedulingTimeout(microtimeout_t to) { schedulingTimeout = to; } inline microtimeout_t getDefaultExpireTimeout() const { return defaultExpireTimeout; } /** * Set the "expired" timer for expiring packets pending in * the send queue which have gone unsent and are already * "too late" to be sent now. * * @param to timeout to expire unsent packets in milliseconds. **/ inline void setExpireTimeout(microtimeout_t to) { expireTimeout = to; } inline microtimeout_t getExpireTimeout() const { return expireTimeout; } /** * Get the total number of packets sent so far * * @return total number of packets sent */ inline uint32 getSendPacketCount() const { return sendInfo.packetCount; } /** * Get the total number of octets (payload only) sent so far. * * @return total number of payload octets sent in RTP packets. **/ inline uint32 getSendOctetCount() const { return sendInfo.octetCount; } /** * Get the sequence number of the next outgoing packet. * * @return the 16 bit sequence number. **/ inline uint16 getSequenceNumber() const { return sendInfo.sendSeq; } /** * Set ouput queue CryptoContext. * * The endQueue method (provided by RTPQueue) deletes all * registered CryptoContexts. * * @param cc Pointer to initialized CryptoContext. */ void setOutQueueCryptoContext(CryptoContext* cc); /** * Remove output queue CryptoContext. * * The endQueue method (provided by RTPQueue) also deletes all * registered CryptoContexts. * * @param cc Pointer to initialized CryptoContext to remove. */ void removeOutQueueCryptoContext(CryptoContext* cc); /** * Get an output queue CryptoContext identified by SSRC * * @param ssrc Request CryptoContext for this incoming SSRC * @return Pointer to CryptoContext of the SSRC of NULL if no context * available for this SSRC. */ CryptoContext* getOutQueueCryptoContext(uint32 ssrc); protected: OutgoingDataQueue(); virtual ~OutgoingDataQueue() { } struct OutgoingRTPPktLink { OutgoingRTPPktLink(OutgoingRTPPkt* pkt, OutgoingRTPPktLink* p, OutgoingRTPPktLink* n) : packet(pkt), prev(p), next(n) { } ~OutgoingRTPPktLink() { delete packet; } inline OutgoingRTPPkt* getPacket() { return packet; } inline void setPacket(OutgoingRTPPkt* pkt) { packet = pkt; } inline OutgoingRTPPktLink* getPrev() { return prev; } inline void setPrev(OutgoingRTPPktLink* p) { prev = p; } inline OutgoingRTPPktLink* getNext() { return next; } inline void setNext(OutgoingRTPPktLink* n) { next = n; } // the packet this link refers to. OutgoingRTPPkt* packet; // global outgoing packets queue. OutgoingRTPPktLink * prev, * next; }; /** * This is used to write the RTP data packet to one or more * destinations. It is used by both sendImmediate and by * dispatchDataPacket. * * @param RTP packet to send. */ void dispatchImmediate(OutgoingRTPPkt *packet); /** * This computes the timeout period for scheduling transmission * of the next packet at the "head" of the send buffer. If no * packets are waiting, a default timeout is used. This actually * forms the "isPending()" timeout of the rtp receiver in the * service thread. * * @return timeout until next packet is scheduled to send. **/ microtimeout_t getSchedulingTimeout(); /** * This function is used by the service thread to process * the next outgoing packet pending in the sending queue. * * @return number of bytes sent. 0 if silent, <0 if error. **/ size_t dispatchDataPacket(); /** * For thoses cases in which the application requires a method * to set the sequence number for the outgoing stream (such as * for implementing the RTSP PLAY command). * * @param seqNum next sequence number to be used for outgoing packets. * **/ inline void setNextSeqNum(uint32 seqNum) { sendInfo.sendSeq = seqNum; } inline uint32 getCurrentSeqNum(void) { return sendInfo.sendSeq; } /** */ inline void setInitialTimestamp(uint32 ts) { initialTimestamp = ts; } /** */ inline uint32 getInitialTimestamp() { return initialTimestamp; } void purgeOutgoingQueue(); virtual void setControlPeer(const InetAddress &host, tpport_t port) {} #ifdef CCXX_IPV6 virtual void setControlPeerIPV6(const IPV6Address &host, tpport_t port) {} #endif // The crypto contexts for outgoing SRTP sessions. mutable Mutex cryptoMutex; std::list<CryptoContext *> cryptoContexts; private: /** * A hook to filter packets being sent that have been expired. * * @param - expired packet from the send queue. **/ inline virtual void onExpireSend(OutgoingRTPPkt&) { } virtual void setDataPeer(const InetAddress &host, tpport_t port) {} #ifdef CCXX_IPV6 virtual void setDataPeerIPV6(const IPV6Address &host, tpport_t port) {} #endif /** * This function performs the physical I/O for writing a * packet to the destination. It is a virtual that is * overriden in the derived class. * * @param buffer Pointer to data to write. * @param len Length of data to write. * @return number of bytes sent. **/ virtual size_t sendData(const unsigned char* const buffer, size_t len) {return 0;} #ifdef CCXX_IPV6 virtual size_t sendDataIPV6(const unsigned char* const buffer, size_t len) {return 0;} #endif static const microtimeout_t defaultSchedulingTimeout; static const microtimeout_t defaultExpireTimeout; mutable ThreadLock sendLock; // outgoing data packets queue OutgoingRTPPktLink* sendFirst, * sendLast; uint32 initialTimestamp; // transmission scheduling timeout for the service thread microtimeout_t schedulingTimeout; // how old a packet can reach in the sending queue before deletetion microtimeout_t expireTimeout; struct { // number of packets sent from the beginning uint32 packetCount; // number of payload octets sent from the beginning uint32 octetCount; // the sequence number of the next packet to sent uint16 sendSeq; // contributing sources uint32 sendSources[16]; // how many CSRCs to send. uint16 sendCC; // pad packets to a paddinglen multiple uint8 paddinglen; // This flags tells whether to set the bit M in the // RTP fixed header of the packet in which the next // provided data will be sent. bool marked; // whether there was not loss. bool complete; // ramdonly generated offset for the timestamp of sent packets uint32 initialTimestamp; // elapsed time accumulated through successive overflows of // the local timestamp field timeval overflowTime; } sendInfo; }; /** @}*/ // oqueue #ifdef CCXX_NAMESPACES } #endif #endif //CCXX_RTP_OQUEUE_H_ /** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */