ccRTP
rtp.h
Go to the documentation of this file.
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
00002 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
00003 // Copyright (C) 2015 Cherokees of Idaho.
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with GNU ccRTP.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free software
00019 // library without restriction.  Specifically, if other files instantiate
00020 // templates or use macros or inline functions from this file, or you compile
00021 // this file and link it with other files to produce an executable, this
00022 // file does not by itself cause the resulting executable to be covered by
00023 // the GNU General Public License.  This exception does not however
00024 // invalidate any other reasons why the executable file might be covered by
00025 // the GNU General Public License.
00026 //
00027 // This exception applies only to the code released under the name GNU
00028 // ccRTP.  If you copy code from other releases into a copy of GNU
00029 // ccRTP, as the General Public License permits, the exception does
00030 // not apply to the code that you add in this way.  To avoid misleading
00031 // anyone as to the status of such modified files, you must delete
00032 // this exception notice from them.
00033 //
00034 // If you write modifications of your own for GNU ccRTP, it is your choice
00035 // whether to permit this exception to apply to your modifications.
00036 // If you do not wish that, delete this exception notice.
00037 //
00038 
00050 #ifndef CCXX_RTP_RTP_H_
00051 #define CCXX_RTP_RTP_H_
00052 
00053 #include <ccrtp/cqueue.h>
00054 #include <ccrtp/channel.h>
00055 
00056 NAMESPACE_COMMONCPP
00057 
00084     template <class RTPDataChannel = DualRTPUDPIPv4Channel,
00085           class RTCPChannel = DualRTPUDPIPv4Channel,
00086           class ServiceQueue = AVPQueue>
00087     class __EXPORT TRTPSessionBase : public ServiceQueue
00088     {
00089     public:
00099         TRTPSessionBase(const InetHostAddress& ia, tpport_t dataPort,
00100                 tpport_t controlPort, uint32 membersSize,
00101                 RTPApplication& app) :
00102             ServiceQueue(membersSize,app)
00103             { build(ia,dataPort,controlPort); }
00104 
00116         TRTPSessionBase(uint32 ssrc,
00117                 const InetHostAddress& ia,
00118                 tpport_t dataPort, tpport_t controlPort,
00119                 uint32 membersSize, RTPApplication& app):
00120             ServiceQueue(ssrc,membersSize,app)
00121             { build(ia,dataPort,controlPort); }
00122 
00135         TRTPSessionBase(const InetMcastAddress& ia, tpport_t dataPort,
00136                 tpport_t controlPort, uint32 membersSize,
00137                 RTPApplication& app, uint32 iface) :
00138             ServiceQueue(membersSize,app)
00139             { build(ia,dataPort,controlPort,iface); }
00140 
00155         TRTPSessionBase(uint32 ssrc,
00156                 const InetMcastAddress& ia, tpport_t dataPort,
00157                 tpport_t controlPort, uint32 membersSize,
00158                 RTPApplication& app, uint32 iface) :
00159             ServiceQueue(ssrc,membersSize,app)
00160             { build(ia,dataPort,controlPort,iface); }
00161 
00162         virtual size_t dispatchBYE(const std::string &str)
00163             {
00164                 return QueueRTCPManager::dispatchBYE(str);
00165             }
00166 
00173         inline Socket::Error
00174         setMcastTTL(uint8 ttl)
00175             {
00176                 Socket::Error error = dso->setMulticast(true);
00177                 if ( error ) return error;
00178                 error = dso->setTimeToLive(ttl);
00179                 if ( error ) return error;
00180                 error = cso->setMulticast(true);
00181                 if ( error ) return error;
00182                 return cso->setTimeToLive(ttl);
00183             }
00184 
00185         inline virtual
00186         ~TRTPSessionBase()
00187             {
00188                 endSocket();
00189             }
00190 
00191         inline RTPDataChannel *getDSO(void)
00192             {return dso;}
00193 
00194     protected:
00198         inline bool
00199         isPendingData(microtimeout_t timeout)
00200             { return dso->isPendingRecv(timeout); }
00201 
00202         InetHostAddress
00203         getDataSender(tpport_t *port = NULL) const
00204             { return dso->getSender(port); }
00205 
00206         inline size_t
00207         getNextDataPacketSize() const
00208             { return dso->getNextPacketSize(); }
00209 
00219         inline size_t
00220         recvData(unsigned char* buffer, size_t len,
00221              InetHostAddress& na, tpport_t& tp)
00222             { na = dso->getSender(tp); return dso->recv(buffer, len); }
00223 
00224         inline void
00225         setDataPeer(const InetAddress &host, tpport_t port)
00226             { dso->setPeer(host,port); }
00227 
00228 
00233         inline size_t
00234         sendData(const unsigned char* const buffer, size_t len)
00235             { return dso->send(buffer, len); }
00236 
00237         inline SOCKET getDataRecvSocket() const
00238             { return dso->getRecvSocket(); }
00239 
00244         inline bool
00245         isPendingControl(microtimeout_t timeout)
00246             { return cso->isPendingRecv(timeout); }
00247 
00248         InetHostAddress
00249         getControlSender(tpport_t *port = NULL) const
00250             { return cso->getSender(port); }
00251 
00261         inline size_t
00262         recvControl(unsigned char *buffer, size_t len,
00263                 InetHostAddress& na, tpport_t& tp)
00264             { na = cso->getSender(tp); return cso->recv(buffer,len); }
00265 
00266         inline void
00267         setControlPeer(const InetAddress &host, tpport_t port)
00268             { cso->setPeer(host,port); }
00269 
00275         inline size_t
00276         sendControl(const unsigned char* const buffer, size_t len)
00277             { return cso->send(buffer,len); }
00278 
00279         inline SOCKET getControlRecvSocket() const
00280             { return cso->getRecvSocket(); }
00281 
00288         inline Socket::Error
00289         joinGroup(const InetMcastAddress& ia, uint32 iface)
00290             {
00291                 Socket::Error error  = dso->setMulticast(true);
00292                 if ( error ) return error;
00293                 error = dso->join(ia,iface);
00294                 if ( error ) return error;
00295                 error = cso->setMulticast(true);
00296                 if ( error ) {
00297                     dso->drop(ia);
00298                     return error;
00299                 }
00300                 error = cso->join(ia,iface);
00301                 if ( error ) {
00302                     dso->drop(ia);
00303                     return error;
00304                 }
00305                 return Socket::errSuccess;
00306             }
00307 
00314         inline Socket::Error
00315         leaveGroup(const InetMcastAddress& ia)
00316             {
00317                 Socket::Error error = dso->setMulticast(false);
00318                 if ( error ) return error;
00319                 error = dso->leaveGroup(ia);
00320                 if ( error ) return error;
00321                 error = cso->setMulticast(false);
00322                 if ( error ) return error;
00323                 return cso->leaveGroup(ia);
00324             }
00325 
00326         inline void
00327         endSocket()
00328             {
00329                 if (dso) {
00330                     dso->endSocket();
00331                     delete dso;
00332                 }
00333                 dso = NULL;
00334                 if (cso) {
00335                     cso->endSocket();
00336                     delete cso;
00337                 }
00338                 cso = NULL;
00339             }
00340 
00341     private:
00342         void
00343         build(const InetHostAddress& ia, tpport_t dataPort,
00344               tpport_t controlPort)
00345             {
00346                 if ( 0 == controlPort ) {
00347                     dataBasePort = even_port(dataPort);
00348                     controlBasePort = dataBasePort + 1;
00349                 } else {
00350                     dataBasePort = dataPort;
00351                     controlBasePort = controlPort;
00352                 }
00353                 dso = new RTPDataChannel(ia,dataBasePort);
00354                 cso = new RTCPChannel(ia,controlBasePort);
00355             }
00356 
00357         void
00358         build(const InetMcastAddress& ia, tpport_t dataPort,
00359               tpport_t controlPort, uint32 iface)
00360             {
00361                 if ( 0 == controlPort ) {
00362                     dataBasePort = even_port(dataPort);
00363                     controlBasePort = dataBasePort + 1;
00364                 } else {
00365                     dataBasePort = dataPort;
00366                     controlBasePort = controlPort;
00367                 }
00368                 dso = new RTPDataChannel(InetHostAddress("0.0.0.0"),dataBasePort);
00369                 cso = new RTCPChannel(InetHostAddress("0.0.0.0"),controlBasePort);
00370                 joinGroup(ia,iface);
00371             }
00372 
00380         inline tpport_t
00381         odd_port(tpport_t port)
00382             { return (port & 0x01)? (port) : (port - 1); }
00383 
00391         inline tpport_t
00392         even_port(tpport_t port)
00393             { return (port & 0x01)? (port - 1) : (port); }
00394 
00395         tpport_t dataBasePort;
00396         tpport_t controlBasePort;
00397 
00398     protected:
00399         RTPDataChannel* dso;
00400         RTCPChannel* cso;
00401         friend class RTPSessionBaseHandler;
00402     };
00403 
00414     template
00415     <class RTPDataChannel = DualRTPUDPIPv4Channel,
00416      class RTCPChannel = DualRTPUDPIPv4Channel,
00417      class ServiceQueue = AVPQueue>
00418     class __EXPORT SingleThreadRTPSession :
00419         protected Thread,
00420         public TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00421     {
00422     public:
00423         SingleThreadRTPSession(const InetHostAddress& ia,
00424                        tpport_t dataPort = DefaultRTPDataPort,
00425                        tpport_t controlPort = 0,
00426                        int pri = 0,
00427                        uint32 memberssize =
00428                        MembershipBookkeeping::defaultMembersHashSize,
00429                        RTPApplication& app = defaultApplication()
00430 #if defined(_MSC_VER) && _MSC_VER >= 1300
00431             );
00432 #else
00433         ):
00434         Thread(pri),
00435         TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00436         (ia,dataPort,controlPort,memberssize,app)
00437         { }
00438 #endif
00439 
00440         SingleThreadRTPSession(uint32 ssrc, const InetHostAddress& ia,
00441                                tpport_t dataPort = DefaultRTPDataPort,
00442                                tpport_t controlPort = 0,
00443                                int pri = 0,
00444                                uint32 memberssize =
00445                                MembershipBookkeeping::defaultMembersHashSize,
00446                                RTPApplication& app = defaultApplication()
00447 #if defined(_MSC_VER) && _MSC_VER >= 1300
00448         );
00449 #else
00450     ):
00451     Thread(pri),
00452     TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00453     (ssrc, ia,dataPort,controlPort,memberssize,app)
00454 { }
00455 #endif
00456 
00457 SingleThreadRTPSession(const InetMcastAddress& ia,
00458                tpport_t dataPort = DefaultRTPDataPort,
00459                tpport_t controlPort = 0,
00460                int pri = 0,
00461                uint32 memberssize =
00462                MembershipBookkeeping::defaultMembersHashSize,
00463                RTPApplication& app = defaultApplication(),
00464                uint32 iface = 0
00465 #if defined(_MSC_VER) && _MSC_VER >= 1300
00466            );
00467 #else
00468         ):
00469         Thread(pri),
00470         TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00471         (ia,dataPort,controlPort,memberssize,app,iface)
00472         { }
00473 #endif
00474 
00475 SingleThreadRTPSession(uint32 ssrc, const InetMcastAddress& ia,
00476                tpport_t dataPort = DefaultRTPDataPort,
00477                tpport_t controlPort = 0,
00478                int pri = 0,
00479                uint32 memberssize =
00480                MembershipBookkeeping::defaultMembersHashSize,
00481                RTPApplication& app = defaultApplication(),
00482                uint32 iface = 0
00483 #if defined(_MSC_VER) && _MSC_VER >= 1300
00484                       );
00485 #else
00486                 ):
00487                 Thread(pri),
00488                 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00489                 (ssrc,ia,dataPort,controlPort,memberssize,app,iface)
00490 { }
00491 #endif
00492 
00493 
00494 ~SingleThreadRTPSession()
00495 {
00496     if (isRunning()) {
00497         disableStack(); Thread::join();
00498     }
00499 }
00500 
00501 #if defined(_MSC_VER) && _MSC_VER >= 1300
00502 virtual void startRunning();
00503 #else
00504 
00507 void
00508 startRunning()
00509 { enableStack(); Thread::start(); }
00510 #endif
00511 
00512 
00513 protected:
00514 inline void disableStack(void)
00515 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();}
00516 
00517 inline void enableStack(void)
00518 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();}
00519 
00520 inline microtimeout_t getSchedulingTimeout(void)
00521 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();}
00522 
00523 inline void controlReceptionService(void)
00524 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();}
00525 
00526 inline void controlTransmissionService(void)
00527 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();}
00528 
00529 inline timeval getRTCPCheckInterval(void)
00530 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();}
00531 
00532 inline size_t dispatchDataPacket(void)
00533 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();}
00534 
00535 #if defined(_MSC_VER) && _MSC_VER >= 1300
00536 virtual void run(void);
00537 
00538 virtual void timerTick(void);
00539 
00540 virtual bool isPendingData(microtimeout_t timeout);
00541 #else
00542 
00543 virtual void timerTick(void)
00544 {return;}
00545 
00546 virtual bool isPendingData(microtimeout_t timeout)
00547 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);}
00548 
00553 virtual void run(void)
00554 {
00555     microtimeout_t timeout = 0;
00556     while ( ServiceQueue::isActive() ) {
00557         if ( timeout < 1000 ){ // !(timeout/1000)
00558             timeout = getSchedulingTimeout();
00559         }
00560         controlReceptionService();
00561         controlTransmissionService();
00562         microtimeout_t maxWait =
00563             timeval2microtimeout(getRTCPCheckInterval());
00564         // make sure the scheduling timeout is
00565         // <= the check interval for RTCP
00566         // packets
00567         timeout = (timeout > maxWait)? maxWait : timeout;
00568         if ( timeout < 1000 ) { // !(timeout/1000)
00569             dispatchDataPacket();
00570             timerTick();
00571         } else {
00572             if ( isPendingData(timeout/1000) ) {
00573                                 if (ServiceQueue::isActive()) { // take in only if active
00574                                     takeInDataPacket();
00575                                 }
00576             }
00577             timeout = 0;
00578         }
00579     }
00580     dispatchBYE("GNU ccRTP stack finishing.");
00581 //        Thread::exit();
00582 }
00583 
00584 #endif
00585 
00586 inline size_t takeInDataPacket(void)
00587 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();}
00588 
00589 inline size_t dispatchBYE(const std::string &str)
00590 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);}
00591 };
00592 
00601 typedef SingleThreadRTPSession<> RTPSession;
00602 
00608 typedef RTPSession RTPSocket;
00609 
00618 typedef SingleThreadRTPSession<SymmetricRTPChannel,
00619                    SymmetricRTPChannel> SymmetricRTPSession;
00620 
00621 #ifdef  CCXX_IPV6
00622 
00644 template <class RTPDataChannel = DualRTPUDPIPv6Channel,
00645       class RTCPChannel = DualRTPUDPIPv6Channel,
00646       class ServiceQueue = AVPQueue>
00647 class __EXPORT TRTPSessionBaseIPV6 : public ServiceQueue
00648 {
00649 public:
00659 TRTPSessionBaseIPV6(const IPV6Host& ia, tpport_t dataPort,
00660     tpport_t controlPort, uint32 membersSize,
00661     RTPApplication& app) :
00662     ServiceQueue(membersSize,app)
00663 { build(ia,dataPort,controlPort); }
00664 
00676     TRTPSessionBaseIPV6(uint32 ssrc,
00677                 const IPV6Host& ia,
00678                 tpport_t dataPort, tpport_t controlPort,
00679                 uint32 membersSize, RTPApplication& app):
00680         ServiceQueue(ssrc,membersSize,app)
00681         { build(ia,dataPort,controlPort); }
00682 
00695     TRTPSessionBaseIPV6(const IPV6Multicast& ia, tpport_t dataPort,
00696                 tpport_t controlPort, uint32 membersSize,
00697                 RTPApplication& app, uint32 iface) :
00698         ServiceQueue(membersSize,app)
00699         { build(ia,dataPort,controlPort,iface); }
00700 
00715     TRTPSessionBaseIPV6(uint32 ssrc,
00716                 const IPV6Multicast& ia, tpport_t dataPort,
00717                 tpport_t controlPort, uint32 membersSize,
00718                 RTPApplication& app, uint32 iface) :
00719         ServiceQueue(ssrc,membersSize,app)
00720         { build(ia,dataPort,controlPort,iface); }
00721 
00722     virtual size_t dispatchBYE(const std::string &str)
00723         {
00724             return QueueRTCPManager::dispatchBYE(str);
00725         }
00726 
00727     inline virtual
00728     ~TRTPSessionBaseIPV6()
00729         {
00730             endSocket();
00731         }
00732 
00733     inline RTPDataChannel *getDSO(void)
00734         {return dso;}
00735 
00736 protected:
00740     inline bool
00741     isPendingData(microtimeout_t timeout)
00742         { return dso->isPendingRecv(timeout); }
00743 
00744     inline IPV6Host
00745     getDataSender(tpport_t *port = NULL) const
00746         { return dso->getSender(port); }
00747 
00748     inline size_t
00749     getNextDataPacketSize() const
00750         { return dso->getNextPacketSize(); }
00751 
00761     inline size_t
00762     recvData(unsigned char* buffer, size_t len,
00763          IPV6Host& na, tpport_t& tp)
00764         { na = dso->getSender(tp); return dso->recv(buffer, len); }
00765 
00766         inline void
00767         setDataPeerIPV6(const IPV6Host &host, tpport_t port)
00768         { dso->setPeer(host,port); }
00769 
00774     inline size_t
00775     sendDataIPV6(const unsigned char* const buffer, size_t len)
00776         { return dso->send(buffer, len); }
00777 
00778     inline SOCKET getDataRecvSocket() const
00779         { return dso->getRecvSocket(); }
00780 
00785         inline bool
00786     isPendingControl(microtimeout_t timeout)
00787         { return cso->isPendingRecv(timeout); }
00788 
00789     inline IPV6Host
00790     getControlSender(tpport_t *port = NULL) const
00791         { return cso->getSender(port); }
00792 
00802         inline size_t
00803     recvControl(unsigned char *buffer, size_t len,
00804             IPV6Host& na, tpport_t& tp)
00805         { na = cso->getSender(tp); return cso->recv(buffer,len); }
00806 
00807         inline void
00808         setControlPeerIPV6(const IPV6Host &host, tpport_t port)
00809         { cso->setPeer(host,port); }
00810 
00816         inline size_t
00817     sendControl(const unsigned char* const buffer, size_t len)
00818         { return cso->send(buffer,len); }
00819 
00820     inline SOCKET getControlRecvSocket() const
00821         { return cso->getRecvSocket(); }
00822 
00823     inline void
00824     endSocket()
00825         {
00826             dso->endSocket();
00827             cso->endSocket();
00828             if (dso) delete dso;
00829             dso = NULL;
00830             if (cso) delete cso;
00831             cso = NULL;
00832         }
00833 
00834 private:
00835     void
00836     build(const IPV6Host& ia, tpport_t dataPort,
00837           tpport_t controlPort)
00838         {
00839             if ( 0 == controlPort ) {
00840                 dataBasePort = even_port(dataPort);
00841                 controlBasePort = dataBasePort + 1;
00842             } else {
00843                 dataBasePort = dataPort;
00844                 controlBasePort = controlPort;
00845             }
00846             dso = new RTPDataChannel(ia,dataBasePort);
00847             cso = new RTCPChannel(ia,controlBasePort);
00848         }
00849 
00850     void
00851     build(const IPV6Multicast& ia, tpport_t dataPort,
00852           tpport_t controlPort, uint32 iface)
00853         {
00854             if ( 0 == controlPort ) {
00855                 dataBasePort = even_port(dataPort);
00856                 controlBasePort = dataBasePort + 1;
00857             } else {
00858                 dataBasePort = dataPort;
00859                 controlBasePort = controlPort;
00860             }
00861             dso = new RTPDataChannel(IPV6Host("0.0.0.0"),dataBasePort);
00862             cso = new RTCPChannel(IPV6Host("0.0.0.0"),controlBasePort);
00863             joinGroup(ia,iface);
00864         }
00865 
00872     inline Socket::Error
00873     joinGroup(const IPV6Multicast& ia, uint32 iface)
00874         {
00875             Socket::Error error  = dso->setMulticast(true);
00876             if ( error ) return error;
00877             error = dso->join(ia,iface);
00878             if ( error ) return error;
00879             error = cso->setMulticast(true);
00880             if ( error ) {
00881                 dso->drop(ia);
00882                 return error;
00883             }
00884             error = cso->join(ia,iface);
00885             if ( error ) {
00886                 dso->drop(ia);
00887                 return error;
00888             }
00889             return Socket::errSuccess;
00890         }
00891 
00898     inline Socket::Error
00899     leaveGroup(const IPV6Multicast& ia)
00900         {
00901             Socket::Error error = dso->setMulticast(false);
00902             if ( error ) return error;
00903             error = dso->leaveGroup(ia);
00904             if ( error ) return error;
00905             error = cso->setMulticast(false);
00906             if ( error ) return error;
00907             return cso->leaveGroup(ia);
00908         }
00909 
00916     inline Socket::Error
00917     setMcastTTL(uint8 ttl)
00918         {
00919             Socket::Error error = dso->setMulticast(true);
00920             if ( error ) return error;
00921             error = dso->setTimeToLive(ttl);
00922             if ( error ) return error;
00923             error = cso->setMulticast(true);
00924             if ( error ) return error;
00925             return cso->setTimeToLive(ttl);
00926         }
00927 
00935     inline tpport_t
00936     odd_port(tpport_t port)
00937         { return (port & 0x01)? (port) : (port - 1); }
00938 
00946     inline tpport_t
00947     even_port(tpport_t port)
00948         { return (port & 0x01)? (port - 1) : (port); }
00949 
00950     tpport_t dataBasePort;
00951     tpport_t controlBasePort;
00952 
00953 protected:
00954     RTPDataChannel* dso;
00955     RTCPChannel* cso;
00956     friend class RTPSessionBaseHandler;
00957 };
00958 
00969 template
00970 <class RTPDataChannel = DualRTPUDPIPv6Channel,
00971  class RTCPChannel = DualRTPUDPIPv6Channel,
00972  class ServiceQueue = AVPQueue>
00973 class __EXPORT SingleThreadRTPSessionIPV6 :
00974     protected Thread,
00975     public TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
00976 {
00977 public:
00978     SingleThreadRTPSessionIPV6(const IPV6Host& ia,
00979                    tpport_t dataPort = DefaultRTPDataPort,
00980                    tpport_t controlPort = 0,
00981                    int pri = 0,
00982                    uint32 memberssize =
00983                    MembershipBookkeeping::defaultMembersHashSize,
00984                    RTPApplication& app = defaultApplication()
00985 #if defined(_MSC_VER) && _MSC_VER >= 1300
00986         );
00987 #else
00988     ):
00989     Thread(pri),
00990     TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
00991     (ia,dataPort,controlPort,memberssize,app)
00992 { }
00993 #endif
00994 
00995 SingleThreadRTPSessionIPV6(const IPV6Multicast& ia,
00996                tpport_t dataPort = DefaultRTPDataPort,
00997                tpport_t controlPort = 0,
00998                int pri = 0,
00999                uint32 memberssize =
01000                MembershipBookkeeping::defaultMembersHashSize,
01001                RTPApplication& app = defaultApplication(),
01002                uint32 iface = 0
01003 #if defined(_MSC_VER) && _MSC_VER >= 1300
01004     );
01005 #else
01006         ):
01007         Thread(pri),
01008         TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
01009         (ia,dataPort,controlPort,memberssize,app,iface)
01010 { }
01011 #endif
01012 
01013 ~SingleThreadRTPSessionIPV6()
01014 {
01015     if (isRunning()) {
01016         disableStack(); Thread::join();
01017     }
01018 }
01019 
01020 #if defined(_MSC_VER) && _MSC_VER >= 1300
01021 virtual void startRunning();
01022 #else
01023 
01026 void
01027 startRunning()
01028 { enableStack(); Thread::start(); }
01029 #endif
01030 
01031 
01032 protected:
01033 inline void enableStack(void)
01034 {TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();}
01035 
01036 inline void disableStack(void)
01037 {TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();}
01038 
01039 inline microtimeout_t getSchedulingTimeout(void)
01040 {return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();}
01041 
01042 inline void controlReceptionService(void)
01043 {TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();}
01044 
01045 inline void controlTransmissionService(void)
01046 {TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();}
01047 
01048 inline timeval getRTCPCheckInterval(void)
01049 {return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();}
01050 
01051 inline size_t dispatchDataPacket(void)
01052 {return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();}
01053 
01054 #if defined(_MSC_VER) && _MSC_VER >= 1300
01055 virtual void run(void);
01056 
01057 virtual void timerTick(void);
01058 
01059 virtual bool isPendingData(microtimeout_t timeout);
01060 #else
01061 
01062 virtual void timerTick(void)
01063 {return;}
01064 
01065 virtual bool isPendingData(microtimeout_t timeout)
01066 {return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);}
01067 
01072 virtual void run(void)
01073 {
01074     microtimeout_t timeout = 0;
01075     while ( ServiceQueue::isActive() ) {
01076         if ( timeout < 1000 ){ // !(timeout/1000)
01077             timeout = getSchedulingTimeout();
01078         }
01079         controlReceptionService();
01080         controlTransmissionService();
01081         microtimeout_t maxWait =
01082             timeval2microtimeout(getRTCPCheckInterval());
01083         // make sure the scheduling timeout is
01084         // <= the check interval for RTCP
01085         // packets
01086         timeout = (timeout > maxWait)? maxWait : timeout;
01087         if ( timeout < 1000 ) { // !(timeout/1000)
01088             dispatchDataPacket();
01089             timerTick();
01090         } else {
01091             if ( isPendingData(timeout/1000) ) {
01092                 takeInDataPacket();
01093             }
01094             timeout = 0;
01095         }
01096     }
01097     dispatchBYE("GNU ccRTP stack finishing.");
01098         Thread::exit();
01099 }
01100 
01101 #endif
01102 
01103 inline size_t takeInDataPacket(void)
01104 {return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();}
01105 
01106 inline size_t dispatchBYE(const std::string &str)
01107 {return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);}
01108 };
01109 
01118 typedef SingleThreadRTPSessionIPV6<> RTPSessionIPV6;
01119 
01125 typedef RTPSessionIPV6 RTPSocketIPV6;
01126 
01135  typedef SingleThreadRTPSessionIPV6<SymmetricRTPChannelIPV6,
01136                     SymmetricRTPChannelIPV6> SymmetricRTPSessionIPV6;
01137 
01138 
01139 #endif
01140  // sessions
01142 
01143 END_NAMESPACE
01144 
01145 #endif  //CCXX_RTP_RTP_H_
01146